/* * This file is a part of the SteamWar software. * * Copyright (C) 2025 SteamWar.de-Serverteam * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package de.steamwar.bausystem.world; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.FlatteningWrapper; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.scheduler.BukkitTask; import java.util.HashMap; import java.util.LinkedList; import java.util.ListIterator; import java.util.Map; public class AutoLoader extends AbstractAutoLoader implements Listener { private static final Map players = new HashMap<>(); public static AutoLoader getLoader(Player player){ if(!players.containsKey(player)) return new AutoLoader(player); return players.get(player); } public static boolean hasLoader(Player player){ return players.containsKey(player); } private final Player player; private final BukkitTask task; private final LinkedList actions = new LinkedList<>(); private int ticksBetweenShots = 80; private int ticksBetweenBlocks = 1; private int lastActivation; private int waitTicks; private ListIterator lastAction; private boolean setup; private Location lastLocation; private AutoLoader(Player player){ this.player = player; Bukkit.getPluginManager().registerEvents(this, BauSystem.getPlugin()); task = Bukkit.getScheduler().runTaskTimer(BauSystem.getPlugin(), this::run, 1, 1); players.put(player, this); player.sendMessage(BauSystem.PREFIX + "§7Schieße bitte einmal die Kanone ab"); player.sendMessage(BauSystem.PREFIX + "§7Und starte anschließend den AutoLader mit §8/§eloader start"); setup(); } public void setup(){ print("§aAutoLader im Setup-Modus", false); setup = true; waitTicks = 0; lastActivation = 0; } public void start(){ if(actions.isEmpty()){ print("§cKeine Aktion vorhanden", false); return; } if(!setup){ print("§cAutoLader läuft bereits", false); return; } setup = false; waitTicks = 0; lastActivation = 0; lastAction = actions.listIterator(); print("§aAutoLader gestartet", false); } public void stop(){ print("§cAutoLader gestoppt", false); players.remove(player); HandlerList.unregisterAll(this); if(task != null) task.cancel(); } public void undo(){ if(actions.isEmpty()){ print("§cKeine Aktion vorhanden", false); return; } actions.removeLast(); print("§aUndo erfolgreich", true); } public void wait(int time){ if(time < 1){ print("§cDie Wartezeit ist zu klein", false); return; } print("§aSchusswartezeit §e" + time + " §aTicks§8, zuvor " + ticksBetweenShots, false); ticksBetweenShots = time; } public void blockWait(int time){ if(time < 1){ print("§cDie Wartezeit ist zu klein", false); return; } print("§aSetzwartezeit §e" + time + " §aTicks§8, zuvor " + ticksBetweenBlocks, false); ticksBetweenBlocks = time; } public int getTicksBetweenShots() { return ticksBetweenShots; } public int getTicksBetweenBlocks() { return ticksBetweenBlocks; } public boolean isSetup() { return setup; } @EventHandler public void onBlockPlace(BlockPlaceEvent event){ if(!setup || !event.getPlayer().equals(player)) return; if(event.getBlock().getType() != Material.TNT) return; new TNTPlaceAction(this, event.getBlock().getLocation()); print("§eTNT platziert", true); } //BlockRedstoneEvent? @EventHandler public void onPlayerInteract(PlayerInteractEvent event){ if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) return; if (event.getClickedBlock().getType() == Material.OBSERVER) return; if (event.getPlayer().isSneaking()) return; if (!setup || !event.getPlayer().equals(player)) return; Detoloader detoloader = FlatteningWrapper.impl.onPlayerInteractLoader(event); if (detoloader == null || detoloader.getActivation() < 0) return; if (lastLocation != null && lastLocation.distance(event.getClickedBlock().getLocation()) <= 1) return; if (detoloader.useActive) { new AbstractAutoLoader.RedstoneActivation(this, event.getClickedBlock().getLocation() , detoloader.getActivation() == 0 ? getLastActivation() : detoloader.getActivation() , detoloader.isActive()); } else { new AbstractAutoLoader.TemporaryActivation(this, event.getClickedBlock().getLocation() , detoloader.getActivation()); } print(detoloader.addBack ? "§e" + detoloader.getBlock() + " betätigt" : detoloader.getBlock(), detoloader.addBack); lastLocation = event.getClickedBlock().getLocation(); } @EventHandler public void onLeave(PlayerQuitEvent event){ if(!event.getPlayer().equals(player)) return; stop(); } private void run(){ lastActivation++; if(setup) return; while(lastActivation >= waitTicks){ lastActivation = 0; LoaderAction action = lastAction.next(); if(action.perform()){ waitTicks = action.ticks(); }else{ waitTicks = 1; lastAction.previous(); } if(!lastAction.hasNext()){ lastAction = actions.listIterator(); waitTicks = ticksBetweenShots; } } } @Override Player getPlayer() { return player; } @Override boolean setRedstone(Location location, boolean active){ return FlatteningWrapper.impl.setRedstone(location, active); } @Override LinkedList getActions() { return actions; } @Override void resetLastActivation() { lastActivation = 0; } @Override int getLastActivation() { return lastActivation; } class TNTPlaceAction extends AbstractAutoLoader.LoaderAction { TNTPlaceAction(AbstractAutoLoader loader, Location location){ super(loader, location); } @Override public boolean perform() { return FlatteningWrapper.impl.tntPlaceActionPerform(location); } @Override int ticks(){ return ticksBetweenBlocks; } } }