Schemnodes #56
@ -41,6 +41,7 @@ SCOREBOARD_REGION = Region
|
||||
SCOREBOARD_TRACE = Trace
|
||||
SCOREBOARD_LOADER = Loader
|
||||
SCOREBOARD_TPS = TPS
|
||||
SCOREBOARD_TPS_FROZEN = §e Eingefroren
|
||||
|
||||
SCOREBOARD_TRACE_TICKS = Ticks
|
||||
|
||||
@ -519,20 +520,45 @@ BLOCK_COUNTER_MESSAGE = §e{0} §7Blöcke §e{1} §7TNT §e{2} §7Blöcke/TNT
|
||||
BLOCK_COUNTER_ENABLE = §7BlockCounter angemacht
|
||||
BLOCK_COUNTER_DISABLE = §7BlockCounter ausgemacht
|
||||
|
||||
# TPSLimit
|
||||
TICK_STEP_HELP = §8/§etick step §8<§7Ticks§8> §8- §7Spule n Ticks vor
|
||||
TICK_STEP_SINGLE_HELP = §8/§etick step §8- §7Spule einen Ticks vor
|
||||
TICK_WARP_HELP = §8/§etick warp §8<§7Ticks§8> §8- §7Warpe n Ticks vor
|
||||
TICK_CANCEL_HELP = §8/§etick cancel §8- §7Cancelt den Tick Warp oder Step
|
||||
TICK_ERROR = §cDu kannst keinen weiteren §8'§e/tick step§8'§c oder §8'§e/tick warp§8'§c anmachen
|
||||
TICK_CANCEL_ERROR = §cDu hast keinen §8'§e/tick step§8'§c oder §8'§e/tick warp§8'§c aktiv
|
||||
TICK_STEP = §eSpult {0} Ticks vor
|
||||
TICK_STEP_LEFT = §eSpult noch {0} Ticks vor
|
||||
TICK_WARP = §eWarpe {0} Ticks vor
|
||||
TICK_WARP_LEFT = §eWarpe noch {0} Ticks vor
|
||||
TICK_CANCEL = §eWarps und Steps abgebrochen
|
||||
TPSLIMIT_GUI_ITEM_NAME = §eTPS Limiter
|
||||
TPSLIMIT_GUI_ITEM_LORE = §7Aktuell: §e{0}
|
||||
TPSLIMIT_ANVIL_GUI = Neues TPS Limit
|
||||
TPSLIMIT_HELP = §8/§etpslimit §8[§7TPS§8|§edefault§8] §8- §7Setzte die TPS auf dem Bau
|
||||
TPSLIMIT_CURRENT = §7Jetziges TPS limit§8: §e{0}
|
||||
TPSLIMIT_NO_PERMS = §cDu darfst hier nicht den TPS-Limiter nutzen
|
||||
TPSLIMIT_SET = §eTPS limit auf {0} gesetzt.
|
||||
TPSLIMIT_FROZEN = §eTPS eingefroren.
|
||||
TPSLIMIT_INVALID = §cNur Zahlen zwischen 0,5 und {0}, und 'default'{1} erlaubt.
|
||||
TPSLIMIT_INVALID_FROZEN = §c und '0'
|
||||
|
||||
# Trace
|
||||
TRACE_RECORD=§aan
|
||||
TRACE_RECORD-AUTO=§aan
|
||||
TRACE_RECORD-SINGLE=§aan
|
||||
TRACE_IDLE=§caus
|
||||
TRACE_IDLE-AUTO=§eauto
|
||||
TRACE_IDLE-SINGLE=§esingle
|
||||
TRACE_MESSAGE-AUTO_RECORD=§cTNT-Tracer muss gestoppt werden
|
||||
TRACE_MESSAGE-AUTO_RECORD-AUTO=§cTNT-Tracer darf nicht aufnehmen
|
||||
TRACE_MESSAGE-AUTO_IDLE=§cAuto-Tracer gestoppt
|
||||
TRACE_MESSAGE-AUTO_IDLE-AUTO = §aAuto-Tracer gestartet
|
||||
TRACE_MESSAGE_START = §aTNT-Tracer gestartet
|
||||
TRACE_MESSAGE_SINGLE = §aSingle-Tracer gestartet
|
||||
TRACE_MESSAGE_STOP = §cTNT-Tracer gestoppt
|
||||
TRACE_MESSAGE_DELETE = §cAlle TNT-Positionen gelöscht
|
||||
TRACE_MESSAGE_SHOW = §aAlle TNT-Positionen angezeigt
|
||||
TRACE_MESSAGE_SHOW_UNKNOWN = §cUnbekannter Show Mode
|
||||
TRACE_MESSAGE_HIDE = §cAlle TNT-Positionen ausgeblendet
|
||||
TRACE_MESSAGE_DISALLOWED = §cDu darfst hier nicht den TNT-Tracer nutzen
|
||||
|
||||
|
@ -110,5 +110,4 @@ public class AutostartListener implements Listener {
|
||||
RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT3");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -117,6 +117,8 @@ public class ObserverTracer {
|
||||
}
|
||||
|
||||
private void calculateObserver(Block block) {
|
||||
// TODO: Implement single Repeater, single Redstone, DetectorRail, PoweredRail, Diagonal Piston
|
||||
|
||||
Observer observer = (Observer) block.getBlockData();
|
||||
for (BlockFace blockFace : ALLOWED) {
|
||||
Location location = block.getLocation().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ());
|
||||
|
@ -40,12 +40,20 @@ public class TimeCommand extends SWCommand {
|
||||
addDefaultHelpMessage("OTHER_TIME_HELP");
|
||||
}
|
||||
|
||||
// TODO: Add set as OptionalValue
|
||||
@Register
|
||||
public void genericCommand(@Guard Player p, Time time) {
|
||||
Bukkit.getWorlds().get(0).setTime(time.getValue());
|
||||
BauSystem.MESSAGE.send("OTHER_TIME_RESULT", p);
|
||||
}
|
||||
|
||||
@Register
|
||||
public void genericCommand(@Guard Player p, @StaticValue(value = "set") String set, Time time) {
|
||||
Bukkit.getWorlds().get(0).setTime(time.getValue());
|
||||
BauSystem.MESSAGE.send("OTHER_TIME_RESULT", p);
|
||||
}
|
||||
|
||||
// TODO: Add set as OptionalValue
|
||||
@Register
|
||||
public void genericCommand(@Guard Player p, int time) {
|
||||
if (time < 0 || time > 24000) {
|
||||
@ -56,6 +64,16 @@ public class TimeCommand extends SWCommand {
|
||||
BauSystem.MESSAGE.send("OTHER_TIME_RESULT", p);
|
||||
}
|
||||
|
||||
@Register
|
||||
public void genericCommand(@Guard Player p, @StaticValue(value = "set") String set, int time) {
|
||||
if (time < 0 || time > 24000) {
|
||||
BauSystem.MESSAGE.send("OTHER_TIME_INVALID", p);
|
||||
return;
|
||||
}
|
||||
Bukkit.getWorlds().get(0).setTime(time);
|
||||
BauSystem.MESSAGE.send("OTHER_TIME_RESULT", p);
|
||||
}
|
||||
|
||||
@ClassMapper(value = int.class, local = true)
|
||||
public TypeMapper<Integer> intTypeMapper() {
|
||||
return SWCommandUtils.createMapper(s -> {
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.region;
|
||||
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockFadeEvent;
|
||||
import org.bukkit.event.block.BlockFormEvent;
|
||||
|
||||
@Linked(LinkageType.LISTENER)
|
||||
public class OtherListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onBlockForm(BlockFormEvent event) {
|
||||
if (event.getBlock().getType() == Material.SNOW_BLOCK || event.getBlock().getType() == Material.SNOW) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockFade(BlockFadeEvent event) {
|
||||
if (event.getBlock().getType() == Material.SNOW_BLOCK || event.getBlock().getType() == Material.SNOW) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
@ -26,9 +26,14 @@ import de.steamwar.bausystem.SWUtils;
|
||||
import de.steamwar.bausystem.config.ColorConfig;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import de.steamwar.bausystem.worlddata.SimulatorData;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.command.TypeMapper;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Linked(LinkageType.COMMAND)
|
||||
public class SimulatorCommand extends SWCommand {
|
||||
|
||||
@ -42,6 +47,10 @@ public class SimulatorCommand extends SWCommand {
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "simulator start" + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Startet die Simulation");
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "simulator gui" + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Öffnet die GUI");
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "simulator delete" + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Löscht alle TNT");
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "simulator save <Name>" + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Speichert den Simulator");
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "simulator load <Name>" + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Lädt den Simulator");
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "simulator list" + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Listet alle gespeicherten Simulator");
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "simulator remove <Name>" + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Löscht den Simulator");
|
||||
}
|
||||
|
||||
@Register
|
||||
@ -66,6 +75,44 @@ public class SimulatorCommand extends SWCommand {
|
||||
public void deleteCommand(Player p) {
|
||||
if (cannotUse(p)) return;
|
||||
TNTSimulator.get(p).delete();
|
||||
p.sendMessage(ColorConfig.BASE + "Alle TNT wurden gelöscht");
|
||||
}
|
||||
|
||||
@Register({"save"})
|
||||
public void saveCommand(Player p, String name) {
|
||||
if (cannotUse(p)) return;
|
||||
TNTSimulator.get(p).save();
|
||||
SimulatorData.saveSimulator(p, name);
|
||||
p.sendMessage(ColorConfig.BASE + "Simulator " + ColorConfig.HIGHLIGHT + name + ColorConfig.BASE + " wurde gespeichert");
|
||||
}
|
||||
|
||||
@Register({"load"})
|
||||
public void loadCommand(Player p, @Mapper("SavedSimulators") String name) {
|
||||
if (cannotUse(p)) return;
|
||||
TNTSimulator.get(p).delete();
|
||||
SimulatorData.loadSimulator(p, name);
|
||||
p.sendMessage(ColorConfig.BASE + "Simulator " + ColorConfig.HIGHLIGHT + name + ColorConfig.BASE + " wurde geladen");
|
||||
}
|
||||
|
||||
@Register({"remove"})
|
||||
public void removeCommand(Player p, @Mapper("SavedSimulators") String name) {
|
||||
if (cannotUse(p)) return;
|
||||
SimulatorData.removeSimulator(p, name);
|
||||
p.sendMessage(ColorConfig.BASE + "Simulator " + ColorConfig.HIGHLIGHT + name + ColorConfig.BASE + " wurde gelöscht");
|
||||
}
|
||||
|
||||
@Register({"list"})
|
||||
public void listCommand(Player p) {
|
||||
if (cannotUse(p)) return;
|
||||
List<String> sims = SimulatorData.listSimulator(p);
|
||||
if (sims.isEmpty()) {
|
||||
p.sendMessage(ColorConfig.BASE + "Keine gespeicherten Simulatoren");
|
||||
return;
|
||||
}
|
||||
p.sendMessage(ColorConfig.BASE + "Gespeicherte Simulatoren:");
|
||||
for (String s : sims) {
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "simulator load " + s);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean cannotUse(Player player) {
|
||||
@ -76,4 +123,21 @@ public class SimulatorCommand extends SWCommand {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Mapper(value = "SavedSimulators", local = true)
|
||||
public TypeMapper<String> simulatorListTypeMapper() {
|
||||
return new TypeMapper<String>() {
|
||||
@Override
|
||||
public String map(CommandSender commandSender, String[] previousArguments, String s) {
|
||||
if (SimulatorData.listSimulator(((Player) commandSender)).contains(s)) {
|
||||
return s;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabCompletes(CommandSender commandSender, String[] strings, String s) {
|
||||
return SimulatorData.listSimulator(((Player) commandSender));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -24,14 +24,14 @@ package de.steamwar.bausystem.features.simulator;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.SWUtils;
|
||||
import de.steamwar.bausystem.config.ColorConfig;
|
||||
import de.steamwar.bausystem.configplayer.Config;
|
||||
import de.steamwar.bausystem.features.simulator.show.SimulatorEntityShowMode;
|
||||
import de.steamwar.bausystem.features.tracer.record.RecordStateMachine;
|
||||
import de.steamwar.bausystem.worlddata.SimulatorData;
|
||||
import de.steamwar.bausystem.worlddata.WorldData;
|
||||
import de.steamwar.inventory.SWAnvilInv;
|
||||
import de.steamwar.inventory.SWInventory;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import de.steamwar.inventory.SWListInv;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
@ -56,6 +56,10 @@ public class TNTSimulator {
|
||||
private static final Vector Y_VECTOR = new Vector(0, 0.0625, 0);
|
||||
private static final Vector Z_VECTOR = new Vector(0, 0, 0.0625);
|
||||
|
||||
private static final Vector FX_VECTOR = new Vector(1, 0, 0);
|
||||
private static final Vector FY_VECTOR = new Vector(0, 1, 0);
|
||||
private static final Vector FZ_VECTOR = new Vector(0, 0, 1);
|
||||
|
||||
private static final World WORLD = Bukkit.getWorlds().get(0);
|
||||
private static final List<String> LORE = Collections.singletonList("§eZum Ändern klicken");
|
||||
private static final List<TNTSpawn> EMPTY = new ArrayList<>();
|
||||
@ -82,22 +86,18 @@ public class TNTSimulator {
|
||||
simulator.spawns.forEach(tntSpawn -> {
|
||||
yapionArray.add(tntSpawn.output());
|
||||
});
|
||||
if (yapionArray.isEmpty()) {
|
||||
SimulatorData.removeSimulator(player);
|
||||
} else {
|
||||
SimulatorData.saveSimulator(player, new YAPIONObject().add("", yapionArray));
|
||||
}
|
||||
SimulatorData.saveSimulator(player, yapionArray);
|
||||
simulator.hide();
|
||||
}
|
||||
|
||||
public void saveAndDelete() {
|
||||
save();
|
||||
TNT_SIMULATOR_MAP.remove(player);
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
TNTSimulator simulator = TNT_SIMULATOR_MAP.remove(player);
|
||||
SimulatorData.removeSimulator(player);
|
||||
SimulatorData.removeSimulator(player, "");
|
||||
simulator.hide();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
TNTSimulator simulator = TNT_SIMULATOR_MAP.remove(player);
|
||||
simulator.hide();
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ public class TNTSimulator {
|
||||
return;
|
||||
}
|
||||
if (tntSpawns.size() == 1) {
|
||||
tntSpawns.get(0).editTNT();
|
||||
tntSpawns.get(0).editTNT(spawns);
|
||||
} else {
|
||||
showGUI(new HashSet<>(tntSpawns));
|
||||
}
|
||||
@ -177,6 +177,12 @@ public class TNTSimulator {
|
||||
}
|
||||
|
||||
public void start() {
|
||||
boolean simulatorAutoTrace = Config.getInstance().get(player).getPlainValueOrDefault("simulatorAutoTrace", false);
|
||||
if (simulatorAutoTrace) {
|
||||
RecordStateMachine.commandSingle();
|
||||
player.performCommand("trace show");
|
||||
}
|
||||
|
||||
Map<Integer, List<TNTSpawn>> first = new HashMap<>();
|
||||
Map<Integer, List<TNTSpawn>> second = new HashMap<>();
|
||||
int lastTick = 0;
|
||||
@ -211,7 +217,6 @@ public class TNTSimulator {
|
||||
List<String> lore = new ArrayList<>();
|
||||
lore.add("§7TNT-Anzahl§8: §e" + spawn.count);
|
||||
lore.add("§7Tick§8: §e" + spawn.tickOffset);
|
||||
lore.add("§7Fuse-Tick§8: §e" + spawn.fuseTicks);
|
||||
lore.add("");
|
||||
lore.add("§7x§8: §e" + spawn.position.getX());
|
||||
lore.add("§7y§8: §e" + spawn.position.getY());
|
||||
@ -221,7 +226,9 @@ public class TNTSimulator {
|
||||
return new SWListInv.SWListEntry<>(swItem, spawn);
|
||||
}).sorted(Comparator.comparing(SWListInv.SWListEntry::getObject)).collect(Collectors.toList());
|
||||
|
||||
SWListInv<TNTSpawn> swListInv = new SWListInv<>(player, "Kanonensimulator", false, swListEntryList, (clickType, spawn) -> spawn.editTNT());
|
||||
SWListInv<TNTSpawn> swListInv = new SWListInv<>(player, "Kanonensimulator", false, swListEntryList, (clickType, spawn) -> {
|
||||
spawn.editTNT(tntSpawns);
|
||||
});
|
||||
swListInv.setItem(51, new SWItem(Material.BARRIER, "§cTNT löschen", clickType -> {
|
||||
delete();
|
||||
player.closeInventory();
|
||||
@ -230,9 +237,72 @@ public class TNTSimulator {
|
||||
start();
|
||||
player.closeInventory();
|
||||
}));
|
||||
boolean simulatorAutoTrace = Config.getInstance().get(player).getPlainValueOrDefault("simulatorAutoTrace", false);
|
||||
swListInv.setItem(48, new SWItem(simulatorAutoTrace ? Material.CHAIN_COMMAND_BLOCK : Material.COMMAND_BLOCK, "§eAutoTrace§8: §7" + simulatorAutoTrace, clickType -> {
|
||||
Config.getInstance().get(player).put("simulatorAutoTrace", !simulatorAutoTrace);
|
||||
showGUI(tntSpawns);
|
||||
}));
|
||||
swListInv.setItem(49, new SWItem(Material.MAGENTA_GLAZED_TERRACOTTA, "§eAlle Verschieben", clickType -> {
|
||||
move(tntSpawns);
|
||||
}));
|
||||
swListInv.open();
|
||||
}
|
||||
|
||||
private void move(Set<TNTSpawn> tntSpawns) {
|
||||
SWInventory swInventory = new SWInventory(player, 54, "TNT Verschieben");
|
||||
|
||||
// Position Settings
|
||||
// X Position
|
||||
swInventory.setItem(12, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+0,0625"), false, clickType -> {
|
||||
updatePosition(tntSpawns, vector -> vector.add(clickType.isShiftClick() ? X_VECTOR : FX_VECTOR));
|
||||
move(tntSpawns);
|
||||
}));
|
||||
swInventory.setItem(21, new SWItem(Material.PAPER, "§7x-Position", clickType -> {
|
||||
}));
|
||||
swInventory.setItem(30, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-0,0625"), false, clickType -> {
|
||||
updatePosition(tntSpawns, vector -> vector.subtract(clickType.isShiftClick() ? X_VECTOR : FX_VECTOR));
|
||||
move(tntSpawns);
|
||||
}));
|
||||
|
||||
// Y Position
|
||||
swInventory.setItem(13, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+0,0625"), false, clickType -> {
|
||||
updatePosition(tntSpawns, vector -> vector.add(clickType.isShiftClick() ? Y_VECTOR : FY_VECTOR));
|
||||
move(tntSpawns);
|
||||
}));
|
||||
swInventory.setItem(22, new SWItem(Material.PAPER, "§7y-Position", clickType -> {
|
||||
}));
|
||||
swInventory.setItem(31, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-0,0625"), false, clickType -> {
|
||||
updatePosition(tntSpawns, vector -> vector.subtract(clickType.isShiftClick() ? Y_VECTOR : FY_VECTOR));
|
||||
move(tntSpawns);
|
||||
}));
|
||||
|
||||
// Z Position
|
||||
swInventory.setItem(14, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+0,0625"), false, clickType -> {
|
||||
updatePosition(tntSpawns, vector -> vector.add(clickType.isShiftClick() ? Z_VECTOR : FZ_VECTOR));
|
||||
move(tntSpawns);
|
||||
}));
|
||||
swInventory.setItem(23, new SWItem(Material.PAPER, "§7z-Position", clickType -> {
|
||||
}));
|
||||
swInventory.setItem(32, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-0,0625"), false, clickType -> {
|
||||
updatePosition(tntSpawns, vector -> vector.subtract(clickType.isShiftClick() ? Z_VECTOR : FZ_VECTOR));
|
||||
move(tntSpawns);
|
||||
}));
|
||||
|
||||
swInventory.setItem(53, new SWItem(Material.ARROW, "§eZurück", clickType -> {
|
||||
showGUI(tntSpawns);
|
||||
}));
|
||||
swInventory.open();
|
||||
}
|
||||
|
||||
private void updatePosition(Set<TNTSpawn> tntSpawns, Consumer<Vector> positionChanger) {
|
||||
Set<Vector> vectors = new HashSet<>();
|
||||
for (TNTSpawn tntSpawn : tntSpawns) {
|
||||
if (vectors.add(tntSpawn.position)) {
|
||||
positionChanger.accept(tntSpawn.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<TNTSpawn> getEntity(Entity entity) {
|
||||
List<TNTSpawn> tntSpawns = new ArrayList<>();
|
||||
for (TNTSpawn spawn : spawns) {
|
||||
@ -297,7 +367,7 @@ public class TNTSimulator {
|
||||
}
|
||||
}
|
||||
|
||||
if (player.isSneaking()) {
|
||||
if (!player.isSneaking()) {
|
||||
pos.setX(pos.getBlockX() + 0.5);
|
||||
if (face == null || face.getModY() == 0)
|
||||
pos.setY(pos.getBlockY() + 0.0);
|
||||
@ -325,13 +395,13 @@ public class TNTSimulator {
|
||||
this.position = position;
|
||||
this.entity = entity;
|
||||
show();
|
||||
editTNT();
|
||||
editTNT(spawns);
|
||||
}
|
||||
|
||||
private TNTSpawn(YAPIONObject yapionObject) {
|
||||
this.position = new Vector(yapionObject.getPlainValueOrDefault("positionX", 0.0), yapionObject.getPlainValueOrDefault("positionY", 0.0), yapionObject.getPlainValueOrDefault("positionZ", 0.0));
|
||||
this.entity = SimulatorEntityShowMode.createEntity(player, position, false);
|
||||
this.fuseTicks = yapionObject.getPlainValue("fuseTicks");
|
||||
this.fuseTicks = yapionObject.getPlainValueOrDefault("fuseTicks", 80);
|
||||
this.count = yapionObject.getPlainValue("count");
|
||||
this.tickOffset = yapionObject.getPlainValue("tickOffset");
|
||||
this.xVelocity = yapionObject.getPlainValue("xVelocity");
|
||||
@ -405,137 +475,147 @@ public class TNTSimulator {
|
||||
return -Integer.compare(tickOffset, tntSpawn.tickOffset);
|
||||
}
|
||||
|
||||
private void editTNT() {
|
||||
private void editTNT(Set<TNTSpawn> tntSpawns) {
|
||||
hide();
|
||||
entity.setPosition(position);
|
||||
show();
|
||||
SWInventory swInventory = new SWInventory(player, 54, "TNT konfigurieren");
|
||||
|
||||
// Change Count of spawned TNT
|
||||
swInventory.setItem(1, new SWItem(SWItem.getDye(10), "§7+1", clickType -> {
|
||||
setCount(count + 1);
|
||||
editTNT();
|
||||
swInventory.setItem(1, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+5"), false, clickType -> {
|
||||
setCount(count + (clickType.isShiftClick() ? 5 : 1));
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
SWItem countItem = new SWItem(Material.TNT, "§7TNT-Anzahl §8- §e" + count, LORE, false, clickType -> changeCount(player, "Anzahl TNT", count, c -> {
|
||||
setCount(c);
|
||||
editTNT();
|
||||
}, this::editTNT));
|
||||
editTNT(tntSpawns);
|
||||
}, () -> editTNT(tntSpawns)));
|
||||
countItem.getItemStack().setAmount(count);
|
||||
swInventory.setItem(10, countItem);
|
||||
swInventory.setItem(19, new SWItem(SWItem.getDye(1), "§7-1", clickType -> {
|
||||
setCount(count - 1);
|
||||
editTNT();
|
||||
swInventory.setItem(19, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-5"), false, clickType -> {
|
||||
setCount(count - (clickType.isShiftClick() ? 5 : 1));
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
|
||||
// Change TickOffset
|
||||
swInventory.setItem(2, new SWItem(SWItem.getDye(10), "§7+1", clickType -> {
|
||||
setTickOffset(tickOffset + 1);
|
||||
editTNT();
|
||||
swInventory.setItem(2, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+5"), false, clickType -> {
|
||||
setTickOffset(tickOffset + (clickType.isShiftClick() ? 5 : 1));
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
SWItem tickItem = new SWItem(SWItem.getMaterial("DIODE"), "§7Tick §8- §e" + tickOffset, LORE, false, clickType -> changeCount(player, "Tick Offset", tickOffset, tick -> {
|
||||
setTickOffset(tick);
|
||||
editTNT();
|
||||
}, this::editTNT));
|
||||
editTNT(tntSpawns);
|
||||
}, () -> editTNT(tntSpawns)));
|
||||
tickItem.getItemStack().setAmount(Math.max(tickOffset, 1));
|
||||
swInventory.setItem(11, tickItem);
|
||||
swInventory.setItem(20, new SWItem(SWItem.getDye(1), "§7-1", clickType -> {
|
||||
setTickOffset(tickOffset - 1);
|
||||
editTNT();
|
||||
swInventory.setItem(20, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-5"), false, clickType -> {
|
||||
setTickOffset(tickOffset - (clickType.isShiftClick() ? 5 : 1));
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
|
||||
// Change FuseTicks
|
||||
swInventory.setItem(3, new SWItem(SWItem.getDye(10), "§7+1", clickType -> {
|
||||
setFuseTicks(fuseTicks + 1);
|
||||
editTNT();
|
||||
swInventory.setItem(3, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+5"), false, clickType -> {
|
||||
setFuseTicks(fuseTicks + (clickType.isShiftClick() ? 5 : 1));
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
SWItem fuseTickItem = new SWItem(Material.CLOCK, "§7Lebensdauer §8- §e" + fuseTicks, LORE, false, clickType -> changeCount(player, "Fuse-Ticks", fuseTicks, tick -> {
|
||||
setFuseTicks(tick);
|
||||
editTNT();
|
||||
}, this::editTNT));
|
||||
editTNT(tntSpawns);
|
||||
}, () -> editTNT(tntSpawns)));
|
||||
fuseTickItem.getItemStack().setAmount(Math.max(fuseTicks, 1));
|
||||
swInventory.setItem(12, fuseTickItem);
|
||||
swInventory.setItem(21, new SWItem(SWItem.getDye(1), "§7-1", clickType -> {
|
||||
setFuseTicks(fuseTicks - 1);
|
||||
editTNT();
|
||||
swInventory.setItem(21, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-5"), false, clickType -> {
|
||||
setFuseTicks(fuseTicks - (clickType.isShiftClick() ? 5 : 1));
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
|
||||
// Velocity Settings
|
||||
swInventory.setItem(38, Material.TNT, "TNT", clickType -> {
|
||||
swInventory.setItem(38, Material.TNT, "§7TNT", clickType -> {
|
||||
if (xVelocity || yVelocity || zVelocity) {
|
||||
xVelocity = false;
|
||||
yVelocity = false;
|
||||
zVelocity = false;
|
||||
} else {
|
||||
xVelocity = true;
|
||||
yVelocity = true;
|
||||
zVelocity = true;
|
||||
}
|
||||
editTNT(tntSpawns);
|
||||
});
|
||||
swInventory.setItem(46, new SWItem(getWool(xVelocity), getColor(xVelocity), "§7TNT §eSprung X §8- " + active(xVelocity), clickType -> {
|
||||
xVelocity = !xVelocity;
|
||||
editTNT();
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
swInventory.setItem(29, new SWItem(getWool(yVelocity), getColor(yVelocity), "§7TNT §eSprung Y §8- " + active(yVelocity), clickType -> {
|
||||
yVelocity = !yVelocity;
|
||||
editTNT();
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
swInventory.setItem(48, new SWItem(getWool(zVelocity), getColor(zVelocity), "§7TNT §eSprung Z §8- " + active(zVelocity), clickType -> {
|
||||
zVelocity = !zVelocity;
|
||||
editTNT();
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
|
||||
// Position Settings
|
||||
// X Position
|
||||
swInventory.setItem(5, new SWItem(SWItem.getDye(10), "§7+0,0625", clickType -> {
|
||||
position.add(X_VECTOR);
|
||||
editTNT();
|
||||
swInventory.setItem(5, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+0,0625"), false, clickType -> {
|
||||
position.add(clickType.isShiftClick() ? X_VECTOR : FX_VECTOR);
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
swInventory.setItem(14, new SWItem(Material.PAPER, "§7x-Position §8- §e" + position.getX(), LORE, false, clickType -> {
|
||||
changePosition(player, position.getX(), x -> {
|
||||
position.setX(clamp(x));
|
||||
editTNT();
|
||||
}, this::editTNT);
|
||||
editTNT(tntSpawns);
|
||||
}, () -> editTNT(tntSpawns));
|
||||
}));
|
||||
swInventory.setItem(23, new SWItem(SWItem.getDye(1), "§7-0,0625", clickType -> {
|
||||
position.subtract(X_VECTOR);
|
||||
editTNT();
|
||||
swInventory.setItem(23, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-0,0625"), false, clickType -> {
|
||||
position.subtract(clickType.isShiftClick() ? X_VECTOR : FX_VECTOR);
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
|
||||
// Y Position
|
||||
swInventory.setItem(6, new SWItem(SWItem.getDye(10), "§7+0,0625", clickType -> {
|
||||
position.add(Y_VECTOR);
|
||||
editTNT();
|
||||
swInventory.setItem(6, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+0,0625"), false, clickType -> {
|
||||
position.add(clickType.isShiftClick() ? Y_VECTOR : FY_VECTOR);
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
swInventory.setItem(15, new SWItem(Material.PAPER, "§7y-Position §8- §e" + position.getY(), LORE, false, clickType -> {
|
||||
changePosition(player, position.getY(), y -> {
|
||||
position.setY(clamp(y));
|
||||
editTNT();
|
||||
}, this::editTNT);
|
||||
editTNT(tntSpawns);
|
||||
}, () -> editTNT(tntSpawns));
|
||||
}));
|
||||
swInventory.setItem(24, new SWItem(SWItem.getDye(1), "§7-0,0625", clickType -> {
|
||||
position.subtract(Y_VECTOR);
|
||||
editTNT();
|
||||
swInventory.setItem(24, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-0,0625"), false, clickType -> {
|
||||
position.subtract(clickType.isShiftClick() ? Y_VECTOR : FY_VECTOR);
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
|
||||
// Z Position
|
||||
swInventory.setItem(7, new SWItem(SWItem.getDye(10), "§7+0,0625", clickType -> {
|
||||
position.add(Z_VECTOR);
|
||||
editTNT();
|
||||
swInventory.setItem(7, new SWItem(SWItem.getDye(10), "§7+1", Arrays.asList("§eShift §7Click für §e+0,0625"), false, clickType -> {
|
||||
position.add(clickType.isShiftClick() ? Z_VECTOR : FZ_VECTOR);
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
swInventory.setItem(16, new SWItem(Material.PAPER, "§7z-Position §8- §e" + position.getZ(), LORE, false, clickType -> {
|
||||
changePosition(player, position.getZ(), z -> {
|
||||
position.setZ(clamp(z));
|
||||
editTNT();
|
||||
}, this::editTNT);
|
||||
editTNT(tntSpawns);
|
||||
}, () -> editTNT(tntSpawns));
|
||||
}));
|
||||
swInventory.setItem(25, new SWItem(SWItem.getDye(1), "§7-0,0625", clickType -> {
|
||||
position.subtract(Z_VECTOR);
|
||||
editTNT();
|
||||
swInventory.setItem(25, new SWItem(SWItem.getDye(1), "§7-1", Arrays.asList("§eShift §7Click für §e-0,0625"), false, clickType -> {
|
||||
position.subtract(clickType.isShiftClick() ? Z_VECTOR : FZ_VECTOR);
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
|
||||
// Repeater before Comparator
|
||||
swInventory.setItem(41, new SWItem(comparator ? SWItem.getMaterial("REDSTONE_COMPARATOR_OFF") : SWItem.getMaterial("DIODE"), "§7Gezündet durch §8- §e" + (comparator ? "Comparator" : "Repeater"), clickType -> {
|
||||
swInventory.setItem(42, new SWItem(comparator ? SWItem.getMaterial("REDSTONE_COMPARATOR_OFF") : SWItem.getMaterial("DIODE"), "§7Gezündet durch §8- §e" + (comparator ? "Comparator" : "Repeater"), clickType -> {
|
||||
comparator = !comparator;
|
||||
editTNT();
|
||||
editTNT(tntSpawns);
|
||||
}));
|
||||
|
||||
swInventory.setItem(33, new SWItem(Material.TNT, "§eZündphase hinzufügen", clickType -> {
|
||||
spawns.add(new TNTSpawn(position, entity));
|
||||
}));
|
||||
|
||||
swInventory.setItem(42, new SWItem(Material.ARROW, "§eZurück", clickType -> {
|
||||
showGUI();
|
||||
swInventory.setItem(53, new SWItem(Material.ARROW, "§eZurück", clickType -> {
|
||||
showGUI(tntSpawns);
|
||||
}));
|
||||
|
||||
swInventory.setItem(51, new SWItem(Material.DISPENSER, "§eTNT hinzufügen", clickType -> {
|
||||
@ -544,7 +624,7 @@ public class TNTSimulator {
|
||||
}));
|
||||
|
||||
// Delete tnt
|
||||
swInventory.setItem(43, new SWItem(Material.BARRIER, "§cEntfernen", clickType -> {
|
||||
swInventory.setItem(44, new SWItem(Material.BARRIER, "§cEntfernen", clickType -> {
|
||||
hide();
|
||||
spawns.remove(this);
|
||||
player.closeInventory();
|
||||
|
@ -1,16 +0,0 @@
|
||||
package de.steamwar.bausystem.features.simulator;
|
||||
|
||||
import de.steamwar.bausystem.linkage.Disable;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
|
||||
@Linked(LinkageType.DISABLE_LINK)
|
||||
public class TNTSimulatorDisable implements Disable {
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
for (TNTSimulator simulator : TNTSimulator.TNT_SIMULATOR_MAP.values()) {
|
||||
simulator.save();
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ package de.steamwar.bausystem.features.simulator;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.bausystem.linkage.Disable;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
@ -47,7 +48,8 @@ import static de.steamwar.bausystem.features.simulator.TNTSimulator.WAND;
|
||||
import static de.steamwar.bausystem.features.simulator.TNTSimulator.get;
|
||||
|
||||
@Linked(LinkageType.LISTENER)
|
||||
public class TNTSimulatorListener implements Listener {
|
||||
@Linked(LinkageType.DISABLE_LINK)
|
||||
public class TNTSimulatorListener implements Listener, Disable {
|
||||
|
||||
private boolean permissionCheck(Player player) {
|
||||
if (!Permission.hasPermission(player, Permission.WORLD)) {
|
||||
@ -117,7 +119,6 @@ public class TNTSimulatorListener implements Listener {
|
||||
if (event.getItem() == null || !event.getItem().isSimilar(WAND)) {
|
||||
return;
|
||||
}
|
||||
System.out.println(event);
|
||||
|
||||
event.setCancelled(true);
|
||||
if (!permissionCheck(event.getPlayer())) {
|
||||
@ -140,6 +141,14 @@ public class TNTSimulatorListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
get(event.getPlayer()).saveAndDelete();
|
||||
get(event.getPlayer()).save();
|
||||
get(event.getPlayer()).remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
for (TNTSimulator simulator : TNTSimulator.TNT_SIMULATOR_MAP.values()) {
|
||||
simulator.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,15 @@ public class PowerableActivation implements PanzernAlgorithm {
|
||||
if (block.getType() == Material.TNT) {
|
||||
powerable++;
|
||||
}
|
||||
if (blockFace == BlockFace.DOWN || blockFace == BlockFace.UP) {
|
||||
if (blockFace == BlockFace.DOWN) {
|
||||
for (BlockFace otherBlockFace : HORIZONTAL_FACES) {
|
||||
Block otherBlock = block.getRelative(otherBlockFace);
|
||||
if (otherBlock.getType() == Material.PISTON) {
|
||||
powered++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (blockFace == BlockFace.UP) {
|
||||
continue;
|
||||
}
|
||||
switch (block.getType()) {
|
||||
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.smartplace;
|
||||
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
public interface SmartPlaceBehaviour {
|
||||
|
||||
enum SmartPlaceResult {
|
||||
APPLIED,
|
||||
IGNORED
|
||||
}
|
||||
|
||||
enum SmartPlaceType {
|
||||
PLACE,
|
||||
INTERACT_DIRECT, // Before checking if block is interacteable
|
||||
INTERACT_INDIRECT, // After checking if block is interacteable
|
||||
}
|
||||
|
||||
SmartPlaceType getType();
|
||||
default SmartPlaceResult place(BlockPlaceEvent event) {
|
||||
return SmartPlaceResult.IGNORED;
|
||||
}
|
||||
default SmartPlaceResult interact(PlayerInteractEvent event) {
|
||||
return SmartPlaceResult.IGNORED;
|
||||
}
|
||||
}
|
@ -23,41 +23,39 @@ import de.steamwar.bausystem.configplayer.Config;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.block.data.Rotatable;
|
||||
import org.bukkit.block.data.type.Repeater;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
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.inventory.InventoryHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Linked(LinkageType.LISTENER)
|
||||
public class SmartPlaceListener implements Listener {
|
||||
|
||||
private static List<SmartPlaceBehaviour> smartPlaceBehaviours = new ArrayList<>();
|
||||
|
||||
public static void add(SmartPlaceBehaviour smartPlaceBehaviour) {
|
||||
smartPlaceBehaviours.add(smartPlaceBehaviour);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBlockPlace(BlockPlaceEvent event) {
|
||||
if (event.getPlayer().isSneaking() && Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) {
|
||||
Block block = event.getBlockPlaced();
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (blockData instanceof Directional) {
|
||||
Directional directional = (Directional) blockData;
|
||||
BlockFace blockFace = directional.getFacing().getOppositeFace();
|
||||
if (directional.getFaces().contains(blockFace)) {
|
||||
directional.setFacing(blockFace);
|
||||
SmartPlaceBehaviour.SmartPlaceResult smartPlaceResult = SmartPlaceBehaviour.SmartPlaceResult.IGNORED;
|
||||
for (SmartPlaceBehaviour smartPlaceBehaviour : smartPlaceBehaviours) {
|
||||
if (smartPlaceBehaviour.getType() == SmartPlaceBehaviour.SmartPlaceType.PLACE) {
|
||||
smartPlaceBehaviour.place(event);
|
||||
}
|
||||
if (smartPlaceResult == SmartPlaceBehaviour.SmartPlaceResult.APPLIED) {
|
||||
break;
|
||||
}
|
||||
} else if (blockData instanceof Rotatable) {
|
||||
Rotatable rotatable = (Rotatable) blockData;
|
||||
rotatable.setRotation(rotatable.getRotation());
|
||||
}
|
||||
block.setBlockData(blockData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,20 +65,14 @@ public class SmartPlaceListener implements Listener {
|
||||
if (event.getPlayer().getGameMode() == GameMode.SPECTATOR) return;
|
||||
if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) return;
|
||||
|
||||
// Reverse repeater
|
||||
if (event.getPlayer().isSneaking()) {
|
||||
if (event.getClickedBlock().getType() == Material.REPEATER) {
|
||||
if (event.getItem() != null && event.getMaterial() != Material.REPEATER) {
|
||||
for (SmartPlaceBehaviour smartPlaceBehaviour : smartPlaceBehaviours) {
|
||||
SmartPlaceBehaviour.SmartPlaceResult smartPlaceResult = SmartPlaceBehaviour.SmartPlaceResult.IGNORED;
|
||||
if (smartPlaceBehaviour.getType() == SmartPlaceBehaviour.SmartPlaceType.INTERACT_DIRECT) {
|
||||
smartPlaceResult = smartPlaceBehaviour.interact(event);
|
||||
}
|
||||
if (smartPlaceResult == SmartPlaceBehaviour.SmartPlaceResult.APPLIED) {
|
||||
return;
|
||||
}
|
||||
Repeater repeater = (Repeater) event.getClickedBlock().getBlockData();
|
||||
int i = repeater.getDelay() - 1;
|
||||
if (i <= 0) i += 4;
|
||||
repeater.setDelay(i);
|
||||
event.getClickedBlock().setBlockData(repeater);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event.getClickedBlock().getType().isInteractable()) return;
|
||||
@ -95,38 +87,14 @@ public class SmartPlaceListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getClickedBlock().getType() == event.getMaterial() || event.getMaterial() == Material.HOPPER) {
|
||||
if (!(event.getClickedBlock().getState() instanceof InventoryHolder)) {
|
||||
return;
|
||||
for (SmartPlaceBehaviour smartPlaceBehaviour : smartPlaceBehaviours) {
|
||||
SmartPlaceBehaviour.SmartPlaceResult smartPlaceResult = SmartPlaceBehaviour.SmartPlaceResult.IGNORED;
|
||||
if (smartPlaceBehaviour.getType() == SmartPlaceBehaviour.SmartPlaceType.INTERACT_INDIRECT) {
|
||||
smartPlaceResult = smartPlaceBehaviour.interact(event);
|
||||
}
|
||||
} else {
|
||||
BlockData blockData = event.getMaterial().createBlockData();
|
||||
if (blockData instanceof Directional) {
|
||||
return;
|
||||
}
|
||||
if (blockData instanceof Rotatable) {
|
||||
if (smartPlaceResult == SmartPlaceBehaviour.SmartPlaceResult.APPLIED) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Fix block setting
|
||||
event.setUseInteractedBlock(Event.Result.DENY);
|
||||
World world = event.getPlayer().getWorld();
|
||||
Block block = world.getBlockAt(event.getClickedBlock().getX() + event.getBlockFace().getModX(), event.getClickedBlock().getY() + event.getBlockFace().getModY(), event.getClickedBlock().getZ() + event.getBlockFace().getModZ());
|
||||
block.setType(event.getMaterial());
|
||||
BlockData blockData = event.getItem().getType().createBlockData();
|
||||
BlockFace blockFace = event.getBlockFace();
|
||||
if (block.getType() == Material.HOPPER || block.getType() == Material.OBSERVER) {
|
||||
blockFace = blockFace.getOppositeFace();
|
||||
}
|
||||
if (blockData instanceof Directional) {
|
||||
Directional directional = (Directional) blockData;
|
||||
if (directional.getFaces().contains(blockFace)) {
|
||||
directional.setFacing(blockFace);
|
||||
}
|
||||
} else if (blockData instanceof Rotatable) {
|
||||
((Rotatable) blockData).setRotation(blockFace);
|
||||
}
|
||||
block.setBlockData(blockData);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.smartplace.behaviour;
|
||||
|
||||
import de.steamwar.bausystem.features.smartplace.SmartPlaceBehaviour;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.block.data.Rotatable;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
|
||||
@Linked(LinkageType.SMART_PLACE)
|
||||
public class BlockPlaceBehaviour implements SmartPlaceBehaviour {
|
||||
|
||||
@Override
|
||||
public SmartPlaceType getType() {
|
||||
return SmartPlaceType.PLACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmartPlaceResult place(BlockPlaceEvent event) {
|
||||
if (event.getBlockAgainst().getType().isInteractable()) {
|
||||
return SmartPlaceResult.IGNORED;
|
||||
}
|
||||
|
||||
SmartPlaceResult smartPlaceResult = SmartPlaceResult.IGNORED;
|
||||
Block block = event.getBlockPlaced();
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (blockData instanceof Directional) {
|
||||
Directional directional = (Directional) blockData;
|
||||
BlockFace blockFace = directional.getFacing().getOppositeFace();
|
||||
if (directional.getFaces().contains(blockFace)) {
|
||||
directional.setFacing(blockFace);
|
||||
}
|
||||
smartPlaceResult = SmartPlaceResult.APPLIED;
|
||||
} else if (blockData instanceof Rotatable) {
|
||||
Rotatable rotatable = (Rotatable) blockData;
|
||||
rotatable.setRotation(rotatable.getRotation());
|
||||
smartPlaceResult = SmartPlaceResult.APPLIED;
|
||||
}
|
||||
block.setBlockData(blockData);
|
||||
return smartPlaceResult;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.smartplace.behaviour;
|
||||
|
||||
import de.steamwar.bausystem.features.smartplace.SmartPlaceBehaviour;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.block.data.Rotatable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
@Linked(LinkageType.SMART_PLACE)
|
||||
public class BlockRotatingBehaviour implements SmartPlaceBehaviour {
|
||||
|
||||
@Override
|
||||
public SmartPlaceType getType() {
|
||||
return SmartPlaceType.INTERACT_INDIRECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmartPlaceResult interact(PlayerInteractEvent event) {
|
||||
if (event.getClickedBlock().getType() == event.getMaterial() || event.getMaterial() == Material.HOPPER) {
|
||||
if (!(event.getClickedBlock().getState() instanceof InventoryHolder)) {
|
||||
return SmartPlaceResult.IGNORED;
|
||||
}
|
||||
} else {
|
||||
BlockData blockData = event.getMaterial().createBlockData();
|
||||
if (blockData instanceof Directional) {
|
||||
return SmartPlaceResult.IGNORED;
|
||||
}
|
||||
if (blockData instanceof Rotatable) {
|
||||
return SmartPlaceResult.IGNORED;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Fix block setting
|
||||
event.setUseInteractedBlock(Event.Result.DENY);
|
||||
World world = event.getPlayer().getWorld();
|
||||
Block block = world.getBlockAt(event.getClickedBlock().getX() + event.getBlockFace().getModX(), event.getClickedBlock().getY() + event.getBlockFace().getModY(), event.getClickedBlock().getZ() + event.getBlockFace().getModZ());
|
||||
block.setType(event.getMaterial());
|
||||
BlockData blockData = event.getItem().getType().createBlockData();
|
||||
BlockFace blockFace = event.getBlockFace();
|
||||
if (block.getType() == Material.HOPPER || block.getType() == Material.OBSERVER) {
|
||||
blockFace = blockFace.getOppositeFace();
|
||||
}
|
||||
if (blockData instanceof Directional) {
|
||||
Directional directional = (Directional) blockData;
|
||||
if (directional.getFaces().contains(blockFace)) {
|
||||
directional.setFacing(blockFace);
|
||||
}
|
||||
} else if (blockData instanceof Rotatable) {
|
||||
((Rotatable) blockData).setRotation(blockFace);
|
||||
}
|
||||
block.setBlockData(blockData);
|
||||
return SmartPlaceResult.APPLIED;
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.smartplace.behaviour;
|
||||
|
||||
import de.steamwar.bausystem.features.smartplace.SmartPlaceBehaviour;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.type.Repeater;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
@Linked(LinkageType.SMART_PLACE)
|
||||
public class ReverseRepeaterBehaviour implements SmartPlaceBehaviour {
|
||||
|
||||
@Override
|
||||
public SmartPlaceType getType() {
|
||||
return SmartPlaceType.INTERACT_DIRECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmartPlaceResult interact(PlayerInteractEvent event) {
|
||||
if (event.getPlayer().isSneaking()) {
|
||||
if (event.getClickedBlock().getType() == Material.REPEATER) {
|
||||
if (event.getItem() != null && event.getMaterial() != Material.REPEATER) {
|
||||
return SmartPlaceResult.APPLIED;
|
||||
}
|
||||
Repeater repeater = (Repeater) event.getClickedBlock().getBlockData();
|
||||
int i = repeater.getDelay() - 1;
|
||||
if (i <= 0) i += 4;
|
||||
repeater.setDelay(i);
|
||||
event.getClickedBlock().setBlockData(repeater);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return SmartPlaceResult.APPLIED;
|
||||
}
|
||||
return SmartPlaceResult.IGNORED;
|
||||
}
|
||||
}
|
@ -38,6 +38,9 @@ public class BlockCounterListener implements Listener {
|
||||
@EventHandler
|
||||
public void onEntityExplode(EntityExplodeEvent event) {
|
||||
Region region = Region.getRegion(event.getLocation());
|
||||
if (region.isGlobal()) {
|
||||
return;
|
||||
}
|
||||
List<Block> blockList = event.blockList();
|
||||
blockList = blockList.stream().filter(block -> region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)).collect(Collectors.toList());
|
||||
if (blockList.isEmpty()) {
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tpslimit;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.minecraft.server.v1_15_R1.WorldServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
|
||||
import yapion.utils.ReflectionsUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@UtilityClass
|
||||
public class FreezeUtils {
|
||||
|
||||
private static final Field field;
|
||||
public static final boolean freezeEnabled;
|
||||
|
||||
@Getter
|
||||
private static boolean frozen = false;
|
||||
|
||||
private static final World world;
|
||||
|
||||
static {
|
||||
field = ReflectionsUtils.getField(WorldServer.class, "freezed");
|
||||
if (field != null) field.setAccessible(true);
|
||||
freezeEnabled = field != null;
|
||||
world = Bukkit.getWorlds().get(0);
|
||||
}
|
||||
|
||||
public static void freeze() {
|
||||
setFreeze(world, true);
|
||||
}
|
||||
|
||||
public static void unfreeze() {
|
||||
setFreeze(world, false);
|
||||
}
|
||||
|
||||
public static boolean frozen() {
|
||||
return freezeEnabled && frozen;
|
||||
}
|
||||
|
||||
private void setFreeze(World world, boolean state) {
|
||||
if (freezeEnabled) {
|
||||
try {
|
||||
field.set(((CraftWorld) world).getHandle(), state);
|
||||
frozen = state;
|
||||
} catch (IllegalAccessException e) {
|
||||
// Ignored;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,11 +19,11 @@
|
||||
|
||||
package de.steamwar.bausystem.features.tpslimit;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.bausystem.config.ColorConfig;
|
||||
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
|
||||
import de.steamwar.inventory.SWAnvilInv;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import org.bukkit.Material;
|
||||
@ -42,14 +42,14 @@ public class TPSLimitBauGuiItem extends BauGuiItem {
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(Player player) {
|
||||
return new SWItem(Material.CLOCK, ColorConfig.HIGHLIGHT + "TPS Limiter", Arrays.asList(ColorConfig.BASE + "Aktuell: " + ColorConfig.HIGHLIGHT + TPSLimitUtils.getCurrentTPSLimit()), false, clickType -> {
|
||||
return new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_LORE", player, TPSLimitUtils.getCurrentTPSLimit())), false, clickType -> {
|
||||
}).getItemStack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean click(ClickType click, Player p) {
|
||||
p.closeInventory();
|
||||
SWAnvilInv inv = new SWAnvilInv(p, "Neues TPS Limit");
|
||||
SWAnvilInv inv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("TPSLIMIT_ANVIL_GUI", p));
|
||||
inv.setItem(Material.CLOCK);
|
||||
inv.setCallback(s -> p.performCommand("tpslimit " + s));
|
||||
inv.open();
|
||||
|
@ -21,15 +21,13 @@ package de.steamwar.bausystem.features.tpslimit;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.bausystem.config.ColorConfig;
|
||||
import de.steamwar.bausystem.SWUtils;
|
||||
import de.steamwar.bausystem.linkage.Enable;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.command.SWCommandUtils;
|
||||
import de.steamwar.command.TypeMapper;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@ -50,6 +48,10 @@ public class TPSLimitCommand extends SWCommand implements Enable {
|
||||
tabCompletions.add(i + "");
|
||||
}
|
||||
}
|
||||
if (FreezeUtils.freezeEnabled) {
|
||||
tabCompletions.add("0");
|
||||
}
|
||||
addDefaultHelpMessage("TPSLIMIT_HELP");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -57,57 +59,70 @@ public class TPSLimitCommand extends SWCommand implements Enable {
|
||||
TPSWarpUtils.init();
|
||||
}
|
||||
|
||||
@Register(help = true)
|
||||
public void genericHelp(Player p, String... args) {
|
||||
p.sendMessage(BauSystem.PREFIX + "Jetziges TPS limit: " + TPSLimitUtils.currentTPSLimit);
|
||||
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "tpslimit " + ColorConfig.OTHER + "[" + ColorConfig.BASE + "TPS" + ColorConfig.OTHER + "|" + ColorConfig.HIGHLIGHT + "default" + ColorConfig.OTHER + "] - " + ColorConfig.BASE + "Setzte die TPS auf dem Bau");
|
||||
@Register
|
||||
public void checkCommand(Player p) {
|
||||
if (!permissionCheck(p)) return;
|
||||
BauSystem.MESSAGE.send("TPSLIMIT_CURRENT", p, TPSLimitUtils.currentTPSLimit);
|
||||
}
|
||||
|
||||
@Register({"default"})
|
||||
public void defaultCommand(Player p) {
|
||||
if (!permissionCheck(p)) return;
|
||||
TPSLimitUtils.currentTPSLimit = 20;
|
||||
TPSLimitUtils.tpsLimiter();
|
||||
sendNewTPSLimitMessage();
|
||||
valueCommand(p, 20D);
|
||||
}
|
||||
|
||||
@Register
|
||||
public void valueCommand(Player p, /*@DoubleRange(min = 0.5, max = 60)*/ double tpsLimitDouble) {
|
||||
if (!permissionCheck(p)) return;
|
||||
if (FreezeUtils.freezeEnabled && tpsLimitDouble == 0) {
|
||||
FreezeUtils.freeze();
|
||||
TPSLimitUtils.currentTPSLimit = 20;
|
||||
TPSLimitUtils.tpsLimiter();
|
||||
sendNewTPSLimitMessage(true);
|
||||
return;
|
||||
}
|
||||
if (tpsLimitDouble < 0.5 || tpsLimitDouble > (TPSWarpUtils.isWarpAllowed() ? 60 : 20)) {
|
||||
sendInvalidArgumentMessage(p);
|
||||
return;
|
||||
}
|
||||
FreezeUtils.unfreeze();
|
||||
TPSLimitUtils.currentTPSLimit = tpsLimitDouble;
|
||||
TPSLimitUtils.tpsLimiter();
|
||||
sendNewTPSLimitMessage();
|
||||
sendNewTPSLimitMessage(false);
|
||||
}
|
||||
|
||||
@ClassMapper(value = double.class, local = true)
|
||||
public TypeMapper<Double> doubleTypeMapper() {
|
||||
return SWCommandUtils.createMapper(s -> {
|
||||
if (s.equalsIgnoreCase("nan")) return -1D;
|
||||
try {
|
||||
return Double.parseDouble(s.replace(',', '.'));
|
||||
} catch (NumberFormatException e) {
|
||||
return 0D;
|
||||
return -1D;
|
||||
}
|
||||
}, s -> tabCompletions);
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
private boolean permissionCheck(Player player) {
|
||||
protected static boolean permissionCheck(Player player) {
|
||||
if (!Permission.hasPermission(player, Permission.WORLD)) {
|
||||
player.sendMessage(BauSystem.PREFIX + ColorConfig.DISABLE + "Du darfst hier nicht den TPS-Limiter nutzen");
|
||||
BauSystem.MESSAGE.send("TPSLIMIT_NO_PERMS", player);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendNewTPSLimitMessage() {
|
||||
Bukkit.getOnlinePlayers().forEach(p -> p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(ColorConfig.HIGHLIGHT + "TPS limit auf " + TPSLimitUtils.currentTPSLimit + " gesetzt.")));
|
||||
private void sendNewTPSLimitMessage(boolean frozen) {
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
if (frozen) {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_FROZEN", player));
|
||||
} else {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_SET", player, TPSLimitUtils.currentTPSLimit));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendInvalidArgumentMessage(Player player) {
|
||||
player.sendMessage(BauSystem.PREFIX + ColorConfig.DISABLE + "Nur Zahlen zwischen 0,5 und " + (TPSWarpUtils.isWarpAllowed() ? 60 : 20) + ", und 'default' erlaubt.");
|
||||
BauSystem.MESSAGE.send("TPSLIMIT_INVALID", player, TPSWarpUtils.isWarpAllowed() ? 60 : 20, FreezeUtils.freezeEnabled ? BauSystem.MESSAGE.parse("TPSLIMIT_INVALID_FROZEN", player) : "");
|
||||
}
|
||||
}
|
@ -86,5 +86,4 @@ public class TPSLimitUtils {
|
||||
currentTPSLimit = d;
|
||||
tpsLimiter();
|
||||
}
|
||||
|
||||
}
|
@ -34,5 +34,4 @@ public class TPSUtils {
|
||||
static {
|
||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> ticksSinceServerStart++, 1, 1);
|
||||
}
|
||||
|
||||
}
|
@ -44,7 +44,7 @@ public class TPSWarpUtils {
|
||||
|
||||
public static void setTPS(double tps) {
|
||||
double d = 50 - (50 / (tps / 20.0));
|
||||
nanoDOffset = Math.max(0, Math.min((long) (d * 1000000), 37500000));
|
||||
nanoDOffset = Math.max(0, Math.min((long) (d * 1000000), 375000000));
|
||||
if (Core.getVersion() != 15) {
|
||||
return;
|
||||
}
|
||||
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tpslimit;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.SWUtils;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Linked(LinkageType.COMMAND)
|
||||
public class TickCommand extends SWCommand {
|
||||
|
||||
private AtomicInteger ticksLeft = null;
|
||||
private Runnable disableTask = null;
|
||||
private Consumer<Integer> ticksLeftActionBar = null;
|
||||
|
||||
public TickCommand() {
|
||||
super("tick");
|
||||
if (!FreezeUtils.freezeEnabled) {
|
||||
unregister();
|
||||
return;
|
||||
}
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (ticksLeft == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ticksLeft.getAndDecrement() <= 0) {
|
||||
disableTask.run();
|
||||
disableTask = null;
|
||||
ticksLeft = null;
|
||||
}
|
||||
if (ticksLeftActionBar != null && ticksLeft != null) {
|
||||
ticksLeftActionBar.accept(ticksLeft.get());
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(BauSystem.getInstance(), 0L, 1L);
|
||||
}
|
||||
|
||||
@Register(value = {"step"}, description = {"TICK_STEP_SINGLE_HELP", "TICK_STEP_HELP"})
|
||||
public void stepCommand(Player p, @OptionalValue("1") int ticks) {
|
||||
if (!TPSLimitCommand.permissionCheck(p)) return;
|
||||
if (ticksLeft != null) {
|
||||
BauSystem.MESSAGE.send("TICK_ERROR", p);
|
||||
return;
|
||||
}
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_STEP", player, ticks));
|
||||
});
|
||||
FreezeUtils.unfreeze();
|
||||
ticksLeft = new AtomicInteger(ticks);
|
||||
disableTask = FreezeUtils::freeze;
|
||||
ticksLeftActionBar = currentTicksLeft -> {
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_STEP_LEFT", player, currentTicksLeft));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@Register(value = {"warp"}, description = "TICK_WARP_HELP")
|
||||
public void warpCommand(Player p, int ticks) {
|
||||
if (!TPSLimitCommand.permissionCheck(p)) return;
|
||||
if (ticksLeft != null) {
|
||||
BauSystem.MESSAGE.send("TICK_ERROR", p);
|
||||
return;
|
||||
}
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_WARP", player, ticks));
|
||||
});
|
||||
boolean frozen = FreezeUtils.frozen();
|
||||
double currentTPSLimit = TPSLimitUtils.currentTPSLimit;
|
||||
TPSLimitUtils.currentTPSLimit = 240;
|
||||
TPSLimitUtils.tpsLimiter();
|
||||
|
||||
FreezeUtils.unfreeze();
|
||||
ticksLeft = new AtomicInteger(ticks);
|
||||
disableTask = () -> {
|
||||
if (frozen) {
|
||||
FreezeUtils.freeze();
|
||||
}
|
||||
TPSLimitUtils.currentTPSLimit = currentTPSLimit;
|
||||
TPSLimitUtils.tpsLimiter();
|
||||
};
|
||||
ticksLeftActionBar = currentTicksLeft -> {
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_WARP_LEFT", player, currentTicksLeft));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@Register(value = {"cancel"}, description = "TICK_CANCEL_HELP")
|
||||
public void cancelCommand(Player p) {
|
||||
if (!TPSLimitCommand.permissionCheck(p)) return;
|
||||
if (ticksLeft == null) {
|
||||
BauSystem.MESSAGE.send("TICK_CANCEL_ERROR", p);
|
||||
return;
|
||||
}
|
||||
ticksLeft.set(0);
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_CANCEL", player));
|
||||
});
|
||||
}
|
||||
}
|
@ -28,22 +28,28 @@ import de.steamwar.bausystem.features.tracer.show.Record;
|
||||
import de.steamwar.bausystem.features.tracer.show.*;
|
||||
import de.steamwar.bausystem.features.tracer.show.mode.BlockShowMode;
|
||||
import de.steamwar.bausystem.features.tracer.show.mode.ParticleShowMode;
|
||||
import de.steamwar.bausystem.features.tracer.show.mode.RawEntityShowMode;
|
||||
import de.steamwar.bausystem.features.tracer.show.mode.TraceEntityShowMode;
|
||||
import de.steamwar.bausystem.linkage.LinkageType;
|
||||
import de.steamwar.bausystem.linkage.Linked;
|
||||
import de.steamwar.bausystem.shared.ShowMode;
|
||||
import de.steamwar.bausystem.utils.ListChatView;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.command.SWCommandUtils;
|
||||
import de.steamwar.command.TypeMapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import net.md_5.bungee.api.chat.ClickEvent;
|
||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@Linked(LinkageType.COMMAND)
|
||||
public class TraceCommand extends SWCommand {
|
||||
@ -114,8 +120,8 @@ public class TraceCommand extends SWCommand {
|
||||
listCommand(p, 0);
|
||||
}
|
||||
|
||||
@Register({"record", "list"})
|
||||
@Register({"list"})
|
||||
@Register(value = {"record", "list"}, noTabComplete = true)
|
||||
@Register(value = {"list"}, noTabComplete = true)
|
||||
public void listCommand(Player player, int page) {
|
||||
if (!permissionCheck(player)) return;
|
||||
ListChatView.chatView(player, StoredRecords.getRecords(), page, record -> {
|
||||
@ -139,19 +145,19 @@ public class TraceCommand extends SWCommand {
|
||||
});
|
||||
}
|
||||
|
||||
@Register({"record", "delete"})
|
||||
@Register(value = {"record", "delete"}, noTabComplete = true)
|
||||
public void recordDelete(Player p, int id) {
|
||||
if (!permissionCheck(p)) return;
|
||||
StoredRecords.remove(id);
|
||||
BauSystem.MESSAGE.send("TRACE_RECORD_DELETE", p);
|
||||
}
|
||||
|
||||
@Register("record")
|
||||
@Register(value = "record", noTabComplete = true)
|
||||
public void recordList(Player p, int record) {
|
||||
recordList(p, record, 0);
|
||||
}
|
||||
|
||||
@Register("record")
|
||||
@Register(value = "record", noTabComplete = true)
|
||||
public void recordList(Player player, int recordID, int page) {
|
||||
if (!permissionCheck(player)) return;
|
||||
Record traceRecord = StoredRecords.get(recordID);
|
||||
@ -180,7 +186,7 @@ public class TraceCommand extends SWCommand {
|
||||
});
|
||||
}
|
||||
|
||||
@Register({"record", "tnt", "delete"})
|
||||
@Register(value = {"record", "tnt", "delete"}, noTabComplete = true)
|
||||
public void deleteRecordTNT(Player player, int recordID, int tntID) {
|
||||
if (!permissionCheck(player)) return;
|
||||
Record record = StoredRecords.get(recordID);
|
||||
@ -192,13 +198,13 @@ public class TraceCommand extends SWCommand {
|
||||
BauSystem.MESSAGE.send("TRACE_TNT_DELETE", player);
|
||||
}
|
||||
|
||||
@Register("record")
|
||||
public void recordTNTPositions(Player player, int recordID, @Mapper("tnt") String tnt, int tntID) {
|
||||
@Register(value = "record", noTabComplete = true)
|
||||
public void recordTNTPositions(Player player, int recordID, @StaticValue("tnt") String tnt, int tntID) {
|
||||
recordTNTPositions(player, recordID, tnt, tntID, 0);
|
||||
}
|
||||
|
||||
@Register("record")
|
||||
public void recordTNTPositions(Player player, int recordID, @Mapper("tnt") String tnt, int tntID, int page) {
|
||||
@Register(value = "record", noTabComplete = true)
|
||||
public void recordTNTPositions(Player player, int recordID, @StaticValue("tnt") String tnt, int tntID, int page) {
|
||||
if (!permissionCheck(player)) return;
|
||||
Record record = StoredRecords.get(recordID);
|
||||
if (record == null) {
|
||||
@ -225,8 +231,8 @@ public class TraceCommand extends SWCommand {
|
||||
});
|
||||
}
|
||||
|
||||
@Register("record")
|
||||
public void recordTNTPositions(Player player, int recordID, @Mapper("tnt") String tnt, int tntID, @Mapper("fuse") String fuse, int fuseTicks) {
|
||||
@Register(value = "record", noTabComplete = true)
|
||||
public void recordTNTPositions(Player player, int recordID, @StaticValue("tnt") String tnt, int tntID, @StaticValue("fuse") String fuse, int fuseTicks) {
|
||||
if (!permissionCheck(player)) return;
|
||||
Record record = StoredRecords.get(recordID);
|
||||
if (record == null) {
|
||||
@ -257,6 +263,13 @@ public class TraceCommand extends SWCommand {
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_START", p);
|
||||
}
|
||||
|
||||
@Register({"single"})
|
||||
public void singleCommand(Player p) {
|
||||
if (!permissionCheck(p)) return;
|
||||
RecordStateMachine.commandSingle();
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SINGLE", p);
|
||||
}
|
||||
|
||||
@Register({"stop"})
|
||||
public void stopCommand(Player p) {
|
||||
if (!permissionCheck(p)) return;
|
||||
@ -264,12 +277,8 @@ public class TraceCommand extends SWCommand {
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_STOP", p);
|
||||
}
|
||||
|
||||
@Register({"toggleauto"})
|
||||
public void toggleAutoCommand(Player p) {
|
||||
autoCommand(p);
|
||||
}
|
||||
|
||||
@Register({"auto"})
|
||||
@Register({"toggleauto"})
|
||||
public void autoCommand(Player p) {
|
||||
if (!permissionCheck(p)) return;
|
||||
RecordStateMachine.commandAuto();
|
||||
@ -311,10 +320,19 @@ public class TraceCommand extends SWCommand {
|
||||
internalShow(p, ShowModeType.PARTICLE, showModeParameterTypes);
|
||||
}
|
||||
|
||||
@Register({"show", "raw"})
|
||||
public void rawShowEntityCommand(Player p, ShowModeParameterType... showModeParameterTypes) {
|
||||
internalShow(p, ShowModeType.RAW_ENTITY, showModeParameterTypes);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private enum ShowModeType {
|
||||
ENTITY,
|
||||
PARTICLE,
|
||||
BLOCK
|
||||
ENTITY(TraceEntityShowMode::new),
|
||||
RAW_ENTITY(RawEntityShowMode::new),
|
||||
PARTICLE(ParticleShowMode::new),
|
||||
BLOCK(BlockShowMode::new);
|
||||
|
||||
private BiFunction<Player, ShowModeParameter, ShowMode<TNTPosition>> showModeBiFunction;
|
||||
}
|
||||
|
||||
private void internalShow(Player p, @NonNull ShowModeType showModeType, ShowModeParameterType... showModeParameterTypes) {
|
||||
@ -323,20 +341,7 @@ public class TraceCommand extends SWCommand {
|
||||
for (ShowModeParameterType showModeParameterType : showModeParameterTypes) {
|
||||
showModeParameterType.getShowModeParameterConsumer().accept(showModeParameter);
|
||||
}
|
||||
switch (showModeType) {
|
||||
case BLOCK:
|
||||
TraceShowManager.show(p, new BlockShowMode(p, showModeParameter));
|
||||
break;
|
||||
case PARTICLE:
|
||||
TraceShowManager.show(p, new ParticleShowMode(p, showModeParameter));
|
||||
break;
|
||||
case ENTITY:
|
||||
TraceShowManager.show(p, new TraceEntityShowMode(p, showModeParameter));
|
||||
break;
|
||||
default:
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW_UNKNOWN", p);
|
||||
return;
|
||||
}
|
||||
TraceShowManager.show(p, showModeType.showModeBiFunction.apply(p, showModeParameter));
|
||||
BauSystem.MESSAGE.send("TRACE_MESSAGE_SHOW", p);
|
||||
}
|
||||
|
||||
@ -361,40 +366,4 @@ public class TraceCommand extends SWCommand {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Mapper(value = "tnt", local = true)
|
||||
public TypeMapper<String> tntTypeMapper() {
|
||||
return new TypeMapper<String>() {
|
||||
@Override
|
||||
public String map(CommandSender commandSender, String[] previousArguments, String s) {
|
||||
if (s.equals("tnt")) {
|
||||
return "tnt";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabCompletes(CommandSender commandSender, String[] strings, String s) {
|
||||
return Collections.singletonList("tnt");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Mapper(value = "fuse", local = true)
|
||||
public TypeMapper<String> fuseTypeMapper() {
|
||||
return new TypeMapper<String>() {
|
||||
@Override
|
||||
public String map(CommandSender commandSender, String[] previousArguments, String s) {
|
||||
if (s.equals("fuse")) {
|
||||
return "fuse";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabCompletes(CommandSender commandSender, String[] strings, String s) {
|
||||
return Collections.singletonList("fuse");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,10 @@
|
||||
|
||||
package de.steamwar.bausystem.features.tracer.record;
|
||||
|
||||
public class RecordStateMachine {
|
||||
private RecordStateMachine() {
|
||||
}
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@UtilityClass
|
||||
public class RecordStateMachine {
|
||||
private static final TraceAutoHandler autoHandler = new TraceAutoHandler();
|
||||
|
||||
private static RecordStatus recordStatus = RecordStatus.IDLE;
|
||||
@ -53,14 +53,32 @@ public class RecordStateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
public static void commandSingle() {
|
||||
if (recordStatus.isTracing())
|
||||
return;
|
||||
|
||||
if (recordStatus != RecordStatus.IDLE_SINGLE) {
|
||||
recordStatus = RecordStatus.IDLE_SINGLE;
|
||||
autoHandler.enable();
|
||||
}
|
||||
}
|
||||
|
||||
static void autoRecord() {
|
||||
recordStart();
|
||||
if (recordStatus == RecordStatus.IDLE_AUTO) {
|
||||
recordStatus = RecordStatus.RECORD_AUTO;
|
||||
} else {
|
||||
recordStatus = RecordStatus.RECORD_SINGLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void autoIdle() {
|
||||
recordStop();
|
||||
if (recordStatus == RecordStatus.RECORD_AUTO) {
|
||||
recordStatus = RecordStatus.IDLE_AUTO;
|
||||
} else {
|
||||
recordStatus = RecordStatus.IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
private static void recordStart() {
|
||||
|
@ -23,8 +23,10 @@ public enum RecordStatus {
|
||||
|
||||
RECORD("TRACE_RECORD", true, "TRACE_MESSAGE-AUTO_RECORD"),
|
||||
RECORD_AUTO("TRACE_RECORD-AUTO", true, "TRACE_MESSAGE-AUTO_RECORD-AUTO"),
|
||||
RECORD_SINGLE("TRACE_RECORD-SINGLE", true, ""),
|
||||
IDLE("TRACE_IDLE", false, "TRACE_MESSAGE-AUTO_IDLE"),
|
||||
IDLE_AUTO("TRACE_IDLE-AUTO", false, "TRACE_MESSAGE-AUTO_IDLE-AUTO");
|
||||
IDLE_AUTO("TRACE_IDLE-AUTO", false, "TRACE_MESSAGE-AUTO_IDLE-AUTO"),
|
||||
IDLE_SINGLE("TRACE_IDLE-SINGLE", false, "");
|
||||
|
||||
String name;
|
||||
boolean tracing;
|
||||
@ -51,5 +53,4 @@ public enum RecordStatus {
|
||||
public String getAutoMessage() {
|
||||
return autoMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,8 +63,10 @@ public class TraceAutoHandler implements Listener {
|
||||
|
||||
if (lastExplosion > 80) {
|
||||
RecordStateMachine.autoIdle();
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,14 +61,14 @@ public class Record {
|
||||
tnt.clear();
|
||||
}
|
||||
|
||||
public TNTRecord get(int id) {
|
||||
public TNTRecord get(long id) {
|
||||
for (TNTRecord record : tnt) {
|
||||
if (record.getId() == id) return record;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void remove(int id) {
|
||||
public void remove(long id) {
|
||||
tnt.removeIf(record -> record.getId() == id);
|
||||
}
|
||||
|
||||
|
@ -40,11 +40,11 @@ public class StoredRecords {
|
||||
records.remove(record);
|
||||
}
|
||||
|
||||
public static void remove(int id) {
|
||||
public static void remove(long id) {
|
||||
records.removeIf(record -> record.getId() == id);
|
||||
}
|
||||
|
||||
public static Record get(int id) {
|
||||
public static Record get(long id) {
|
||||
for (Record record : records) {
|
||||
if (record.getId() == id) return record;
|
||||
}
|
||||
@ -60,5 +60,4 @@ public class StoredRecords {
|
||||
TraceShowManager.clear();
|
||||
RecordStateMachine.postClear();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tracer.show.mode;
|
||||
|
||||
import de.steamwar.bausystem.features.tracer.AbstractTraceEntity;
|
||||
import de.steamwar.bausystem.features.tracer.TNTPosition;
|
||||
import de.steamwar.bausystem.features.tracer.TNTTracer_15;
|
||||
import de.steamwar.bausystem.features.tracer.show.ShowModeParameter;
|
||||
import de.steamwar.bausystem.shared.RoundedPosition;
|
||||
import de.steamwar.bausystem.shared.ShowMode;
|
||||
import de.steamwar.core.VersionedCallable;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Consumer;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class FactoredEntityShowMode implements ShowMode<TNTPosition> {
|
||||
|
||||
private int factor;
|
||||
|
||||
protected final Player player;
|
||||
protected final ShowModeParameter showModeParameter;
|
||||
|
||||
private final Map<RoundedPosition, AbstractTraceEntity> tntEntityMap = new HashMap<>();
|
||||
private final Map<RoundedPosition, AbstractTraceEntity> updateEntityMap = new HashMap<>();
|
||||
|
||||
protected FactoredEntityShowMode(Player player, ShowModeParameter showModeParameter, int factor) {
|
||||
this.player = player;
|
||||
this.showModeParameter = showModeParameter;
|
||||
this.factor = factor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(TNTPosition position) {
|
||||
if (showModeParameter.isExplodeOnly()) {
|
||||
if (!position.isExploded()) {
|
||||
return;
|
||||
}
|
||||
RoundedPosition roundedPosition = new RoundedPosition(position, factor);
|
||||
AbstractTraceEntity entity = tntEntityMap.computeIfAbsent(roundedPosition, pos -> createEntity(player, position.getLocation(), true));
|
||||
entity.display(player, position.isExploded());
|
||||
return;
|
||||
}
|
||||
if (!showModeParameter.isWater() && position.isExploded() && checkWater(position.getLocation())) {
|
||||
// Basic
|
||||
for (TNTPosition pos : position.getRecord().getPositions()) {
|
||||
RoundedPosition roundedPosition = new RoundedPosition(pos, factor);
|
||||
tntEntityMap.computeIfPresent(roundedPosition, (p, tnt) -> {
|
||||
return tnt.hide(player, false) ? null : tnt;
|
||||
});
|
||||
}
|
||||
// Advanced
|
||||
for (TNTPosition pos : position.getRecord().getPositions()) {
|
||||
applyOnPosition(pos, updatePointPosition -> {
|
||||
updateEntityMap.computeIfPresent(new RoundedPosition(updatePointPosition, factor), (p, point) -> {
|
||||
return point.hide(player, false) ? null : point;
|
||||
});
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
RoundedPosition roundedPosition = new RoundedPosition(position, factor);
|
||||
AbstractTraceEntity entity = tntEntityMap.computeIfAbsent(roundedPosition, pos -> createEntity(player, position.getLocation(), true));
|
||||
entity.display(player, position.isExploded());
|
||||
|
||||
applyOnPosition(position, updatePointPosition -> {
|
||||
updateEntityMap.computeIfAbsent(new RoundedPosition(updatePointPosition, factor), pos -> {
|
||||
return createEntity(player, updatePointPosition, false);
|
||||
}).display(player, false);
|
||||
});
|
||||
}
|
||||
|
||||
private boolean checkWater(Vector position) {
|
||||
return VersionedCallable.call(new VersionedCallable<>(() -> TNTTracer_15.inWater(player.getWorld(), position), 15));
|
||||
}
|
||||
|
||||
public static AbstractTraceEntity createEntity(Player player, Vector position, boolean tnt) {
|
||||
return VersionedCallable.call(new VersionedCallable<>(() -> TNTTracer_15.create(player.getWorld(), position, tnt), 15));
|
||||
}
|
||||
|
||||
private void applyOnPosition(TNTPosition position, Consumer<Vector> function) {
|
||||
if (position.getPreviousLocation() == null) return;
|
||||
|
||||
if (showModeParameter.isInterpolate_Y()) {
|
||||
Vector updatePointY = position.getPreviousLocation().clone().setY(position.getLocation().getY());
|
||||
if (!position.getLocation().equals(updatePointY)) {
|
||||
function.accept(updatePointY);
|
||||
}
|
||||
}
|
||||
|
||||
if (showModeParameter.isInterpolate_XZ()) {
|
||||
Vector movement = position.getLocation().clone().subtract(position.getPreviousLocation());
|
||||
Vector updatePointXZ = Math.abs(movement.getX()) > Math.abs(movement.getZ())
|
||||
? position.getLocation().clone().setZ(position.getPreviousLocation().getZ())
|
||||
: position.getLocation().clone().setX(position.getPreviousLocation().getX());
|
||||
if (!position.getLocation().equals(updatePointXZ)) {
|
||||
function.accept(updatePointXZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
tntEntityMap.forEach((roundedPosition, abstractTraceEntity) -> abstractTraceEntity.hide(player, true));
|
||||
tntEntityMap.clear();
|
||||
updateEntityMap.forEach((roundedPosition, abstractTraceEntity) -> abstractTraceEntity.hide(player, true));
|
||||
updateEntityMap.clear();
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 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 <https://www.gnu.org/licenses/>.
|
||||
* /
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.tracer.show.mode;
|
||||
|
||||
import de.steamwar.bausystem.features.tracer.show.ShowModeParameter;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class RawEntityShowMode extends FactoredEntityShowMode {
|
||||
|
||||
public RawEntityShowMode(Player player, ShowModeParameter showModeParameter) {
|
||||
super(player, showModeParameter, -1);
|
||||
}
|
||||
}
|
@ -21,108 +21,12 @@
|
||||
|
||||
package de.steamwar.bausystem.features.tracer.show.mode;
|
||||
|
||||
import de.steamwar.bausystem.features.tracer.AbstractTraceEntity;
|
||||
import de.steamwar.bausystem.features.tracer.TNTPosition;
|
||||
import de.steamwar.bausystem.features.tracer.TNTTracer_15;
|
||||
import de.steamwar.bausystem.features.tracer.show.ShowModeParameter;
|
||||
import de.steamwar.bausystem.shared.RoundedPosition;
|
||||
import de.steamwar.bausystem.shared.ShowMode;
|
||||
import de.steamwar.core.VersionedCallable;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Consumer;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class TraceEntityShowMode implements ShowMode<TNTPosition> {
|
||||
|
||||
protected final Player player;
|
||||
protected final ShowModeParameter showModeParameter;
|
||||
|
||||
private final Map<RoundedPosition, AbstractTraceEntity> tntEntityMap = new HashMap<>();
|
||||
private final Map<RoundedPosition, AbstractTraceEntity> updateEntityMap = new HashMap<>();
|
||||
public class TraceEntityShowMode extends FactoredEntityShowMode {
|
||||
|
||||
public TraceEntityShowMode(Player player, ShowModeParameter showModeParameter) {
|
||||
this.player = player;
|
||||
this.showModeParameter = showModeParameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(TNTPosition position) {
|
||||
if (showModeParameter.isExplodeOnly()) {
|
||||
if (!position.isExploded()) {
|
||||
return;
|
||||
}
|
||||
RoundedPosition roundedPosition = new RoundedPosition(position);
|
||||
AbstractTraceEntity entity = tntEntityMap.computeIfAbsent(roundedPosition, pos -> createEntity(player, position.getLocation(), true));
|
||||
entity.display(player, position.isExploded());
|
||||
return;
|
||||
}
|
||||
if (!showModeParameter.isWater() && position.isExploded() && checkWater(position.getLocation())) {
|
||||
// Basic
|
||||
for (TNTPosition pos : position.getRecord().getPositions()) {
|
||||
RoundedPosition roundedPosition = new RoundedPosition(pos);
|
||||
tntEntityMap.computeIfPresent(roundedPosition, (p, tnt) -> {
|
||||
return tnt.hide(player, false) ? null : tnt;
|
||||
});
|
||||
}
|
||||
// Advanced
|
||||
for (TNTPosition pos : position.getRecord().getPositions()) {
|
||||
applyOnPosition(pos, updatePointPosition -> {
|
||||
updateEntityMap.computeIfPresent(new RoundedPosition(updatePointPosition), (p, point) -> {
|
||||
return point.hide(player, false) ? null : point;
|
||||
});
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
RoundedPosition roundedPosition = new RoundedPosition(position);
|
||||
AbstractTraceEntity entity = tntEntityMap.computeIfAbsent(roundedPosition, pos -> createEntity(player, position.getLocation(), true));
|
||||
entity.display(player, position.isExploded());
|
||||
|
||||
applyOnPosition(position, updatePointPosition -> {
|
||||
updateEntityMap.computeIfAbsent(new RoundedPosition(updatePointPosition), pos -> {
|
||||
return createEntity(player, updatePointPosition, false);
|
||||
}).display(player, false);
|
||||
});
|
||||
}
|
||||
|
||||
private boolean checkWater(Vector position) {
|
||||
return VersionedCallable.call(new VersionedCallable<>(() -> TNTTracer_15.inWater(player.getWorld(), position), 15));
|
||||
}
|
||||
|
||||
public static AbstractTraceEntity createEntity(Player player, Vector position, boolean tnt) {
|
||||
return VersionedCallable.call(new VersionedCallable<>(() -> TNTTracer_15.create(player.getWorld(), position, tnt), 15));
|
||||
}
|
||||
|
||||
private void applyOnPosition(TNTPosition position, Consumer<Vector> function) {
|
||||
if (position.getPreviousLocation() == null) return;
|
||||
|
||||
if (showModeParameter.isInterpolate_Y()) {
|
||||
Vector updatePointY = position.getPreviousLocation().clone().setY(position.getLocation().getY());
|
||||
if (!position.getLocation().equals(updatePointY)) {
|
||||
function.accept(updatePointY);
|
||||
}
|
||||
}
|
||||
|
||||
if (showModeParameter.isInterpolate_XZ()) {
|
||||
Vector movement = position.getLocation().clone().subtract(position.getPreviousLocation());
|
||||
Vector updatePointXZ = Math.abs(movement.getX()) > Math.abs(movement.getZ())
|
||||
? position.getLocation().clone().setZ(position.getPreviousLocation().getZ())
|
||||
: position.getLocation().clone().setX(position.getPreviousLocation().getX());
|
||||
if (!position.getLocation().equals(updatePointXZ)) {
|
||||
function.accept(updatePointXZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
tntEntityMap.forEach((roundedPosition, abstractTraceEntity) -> abstractTraceEntity.hide(player, true));
|
||||
tntEntityMap.clear();
|
||||
updateEntityMap.forEach((roundedPosition, abstractTraceEntity) -> abstractTraceEntity.hide(player, true));
|
||||
updateEntityMap.clear();
|
||||
super(player, showModeParameter, 10);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package de.steamwar.bausystem.features.world;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.loader.Loader;
|
||||
import de.steamwar.bausystem.features.tpslimit.FreezeUtils;
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSLimitUtils;
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSWarpUtils;
|
||||
@ -85,7 +86,11 @@ public class BauScoreboard implements Listener {
|
||||
strings.add(colorCode + BauSystem.MESSAGE.parse("SCOREBOARD_LOADER", p) + "§8: " + BauSystem.MESSAGE.parse(loader != null ? loader.getStage().getChatValue() : "LOADER_OFF", p));
|
||||
|
||||
strings.add("§5");
|
||||
if (FreezeUtils.frozen()) {
|
||||
strings.add(colorCode + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + BauSystem.MESSAGE.parse("SCOREBOARD_TPS_FROZEN", p));
|
||||
} else {
|
||||
strings.add(colorCode + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8 " + tpsColor() + TPSWarpUtils.getTps(TPSWatcher.TPSType.ONE_SECOND) + tpsLimit());
|
||||
}
|
||||
|
||||
int i = strings.size();
|
||||
HashMap<String, Integer> result = new HashMap<>();
|
||||
|
@ -20,13 +20,15 @@
|
||||
package de.steamwar.bausystem.linkage;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.configplayer.ConfigConverter;
|
||||
import de.steamwar.bausystem.configplayer.Config;
|
||||
import de.steamwar.bausystem.configplayer.ConfigConverter;
|
||||
import de.steamwar.bausystem.features.gui.BauGUI;
|
||||
import de.steamwar.bausystem.features.slaves.panzern.Panzern;
|
||||
import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm;
|
||||
import de.steamwar.bausystem.features.script.ScriptExecutor;
|
||||
import de.steamwar.bausystem.features.script.SpecialCommand;
|
||||
import de.steamwar.bausystem.features.slaves.panzern.Panzern;
|
||||
import de.steamwar.bausystem.features.slaves.panzern.PanzernAlgorithm;
|
||||
import de.steamwar.bausystem.features.smartplace.SmartPlaceBehaviour;
|
||||
import de.steamwar.bausystem.features.smartplace.SmartPlaceListener;
|
||||
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
|
||||
import de.steamwar.bausystem.linkage.specific.ScoreboardItem;
|
||||
import de.steamwar.command.SWCommand;
|
||||
@ -58,7 +60,8 @@ public enum LinkageType {
|
||||
SCRIPT_COMMAND(4, false, SpecialCommand.class::isAssignableFrom, o -> ScriptExecutor.SPECIAL_COMMANDS.add((SpecialCommand) o)),
|
||||
CONFIG_CONVERTER(5, false, ConfigConverter.class::isAssignableFrom, o -> Config.addConfigConverter((ConfigConverter) o)),
|
||||
SCOREBOARD(6, false, ScoreboardItem.class::isAssignableFrom, o -> {}),
|
||||
PANZERN(7, false, PanzernAlgorithm.class::isAssignableFrom, o -> Panzern.add((PanzernAlgorithm) o));
|
||||
PANZERN(7, false, PanzernAlgorithm.class::isAssignableFrom, o -> Panzern.add((PanzernAlgorithm) o)),
|
||||
SMART_PLACE(8, false, SmartPlaceBehaviour.class::isAssignableFrom, o -> SmartPlaceListener.add((SmartPlaceBehaviour) o));
|
||||
|
||||
private final int order;
|
||||
|
||||
|
@ -41,12 +41,10 @@ public class LinkageUtils {
|
||||
|
||||
public void link() {
|
||||
internalLinkOrUnlink(false, Linked.class);
|
||||
internalLinkOrUnlink(false, Linked.Linkages.class);
|
||||
internalLinkFields();
|
||||
}
|
||||
|
||||
public void unlink() {
|
||||
internalLinkOrUnlink(true, Linked.Linkages.class);
|
||||
internalLinkOrUnlink(true, Linked.class);
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,6 @@ import java.lang.annotation.*;
|
||||
public @interface Linked {
|
||||
LinkageType value();
|
||||
|
||||
@IndexAnnotated
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
@interface Linkages {
|
||||
|
@ -434,7 +434,7 @@ public class Region {
|
||||
int dz = Math.abs(clipboard.getOrigin().getZ() - clipboard.getMinimumPoint().getZ());
|
||||
if (dz < 2 || dz > prototype.getTestblock().getSizeZ()) {
|
||||
pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2);
|
||||
} else if (clipboard.getDimensions().getZ() < prototype.getTestblock().getSizeZ()) {
|
||||
} else if (clipboard.getDimensions().getZ() != prototype.getTestblock().getSizeZ()) {
|
||||
pastePoint = pastePoint.add(0, 0, clipboard.getDimensions().getZ() / 2 - (clipboard.getOrigin().getZ() - clipboard.getMinimumPoint().getZ()) - 1);
|
||||
} else {
|
||||
pastePoint = pastePoint.add(0, 0, prototype.getTestblock().getSizeZ() / 2);
|
||||
|
@ -36,7 +36,7 @@ public enum Flag implements EnumDisplay {
|
||||
FIRE("FLAG_FIRE", FireMode.class, FireMode.ALLOW, region -> true),
|
||||
DAMAGE("FLAG_DAMAGE", DamageMode.class, DamageMode.ALLOW, region -> false),
|
||||
FREEZE("FLAG_FREEZE", FreezeMode.class, FreezeMode.INACTIVE, region -> true),
|
||||
PROTECT("FLAG_PROTECT", ProtectMode.class, ProtectMode.INACTIVE, region -> region.getFloorLevel() != 0);
|
||||
PROTECT("FLAG_PROTECT", ProtectMode.class, ProtectMode.ACTIVE, region -> region.getFloorLevel() != 0);
|
||||
|
||||
@Getter
|
||||
private static final Set<Flag> flags;
|
||||
|
@ -25,24 +25,44 @@ import java.util.Objects;
|
||||
|
||||
public class RoundedPosition {
|
||||
|
||||
private static final int factor = 10;
|
||||
private static final long factor = 10;
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
private long x;
|
||||
private long y;
|
||||
private long z;
|
||||
|
||||
public RoundedPosition(Position position) {
|
||||
this(position.getLocation().getX(), position.getLocation().getY(), position.getLocation().getZ());
|
||||
}
|
||||
|
||||
public RoundedPosition(Position position, int factor) {
|
||||
this(position.getLocation().getX(), position.getLocation().getY(), position.getLocation().getZ(), factor);
|
||||
}
|
||||
|
||||
public RoundedPosition(Vector vector) {
|
||||
this(vector.getX(), vector.getY(), vector.getZ());
|
||||
}
|
||||
|
||||
public RoundedPosition(Vector vector, int factor) {
|
||||
this(vector.getX(), vector.getY(), vector.getZ(), factor);
|
||||
}
|
||||
|
||||
public RoundedPosition(double x, double y, double z) {
|
||||
this.x = (int) (x * factor);
|
||||
this.y = (int) (y * factor);
|
||||
this.z = (int) (z * factor);
|
||||
this.x = (long) (x * factor);
|
||||
this.y = (long) (y * factor);
|
||||
this.z = (long) (z * factor);
|
||||
}
|
||||
|
||||
public RoundedPosition(double x, double y, double z, long factor) {
|
||||
if (factor == -1) {
|
||||
this.x = Double.doubleToLongBits(x);
|
||||
this.y = Double.doubleToLongBits(y);
|
||||
this.z = Double.doubleToLongBits(z);
|
||||
} else {
|
||||
this.x = (long) (x * factor);
|
||||
this.y = (long) (y * factor);
|
||||
this.z = (long) (z * factor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,10 +25,12 @@ import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import yapion.hierarchy.output.FileOutput;
|
||||
import yapion.hierarchy.types.YAPIONArray;
|
||||
import yapion.hierarchy.types.YAPIONObject;
|
||||
import yapion.parser.YAPIONParser;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
@UtilityClass
|
||||
public class SimulatorData {
|
||||
@ -49,7 +51,7 @@ public class SimulatorData {
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public void saveSimulator(Player player, YAPIONObject yapionObject) {
|
||||
private void internalSaveSimulator(Player player, YAPIONObject yapionObject) {
|
||||
File file = getFile(player);
|
||||
yapionObject.toYAPION(new FileOutput(file)).close();
|
||||
}
|
||||
@ -60,11 +62,34 @@ public class SimulatorData {
|
||||
yapionObject.toYAPION(new FileOutput(file)).close();
|
||||
}
|
||||
|
||||
public void removeSimulator(Player player) {
|
||||
File file = getFile(player);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
public List<String> listSimulator(Player player) {
|
||||
List<String> strings = getSimulator(player).getKeys();
|
||||
strings.remove("");
|
||||
return strings;
|
||||
}
|
||||
|
||||
public void saveSimulator(Player player, String name) {
|
||||
YAPIONObject yapionObject = getSimulator(player);
|
||||
yapionObject.put(name, yapionObject.getArray("").copy());
|
||||
internalSaveSimulator(player, yapionObject);
|
||||
}
|
||||
|
||||
public void saveSimulator(Player player, YAPIONArray simulator) {
|
||||
YAPIONObject yapionObject = getSimulator(player);
|
||||
yapionObject.put("", simulator);
|
||||
internalSaveSimulator(player, yapionObject);
|
||||
}
|
||||
|
||||
public void loadSimulator(Player player, String name) {
|
||||
YAPIONObject yapionObject = getSimulator(player);
|
||||
yapionObject.put("", yapionObject.getArray(name).copy());
|
||||
internalSaveSimulator(player, yapionObject);
|
||||
}
|
||||
|
||||
public void removeSimulator(Player player, String name) {
|
||||
YAPIONObject yapionObject = getSimulator(player);
|
||||
yapionObject.remove(name);
|
||||
internalSaveSimulator(player, yapionObject);
|
||||
}
|
||||
|
||||
private File getFile(Player player) {
|
||||
|
@ -21,6 +21,7 @@
|
||||
sizeX(63)
|
||||
sizeY(256)
|
||||
sizeZ(120)
|
||||
floorOffset(45)
|
||||
testblock{
|
||||
offsetX(13)
|
||||
offsetY(44)
|
||||
@ -37,6 +38,7 @@
|
||||
sizeX(133)
|
||||
sizeY(255)
|
||||
sizeZ(214)
|
||||
floorOffset(45)
|
||||
testblock{
|
||||
offsetX(33)
|
||||
offsetY(44)
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren