forked from SteamWar/SteamWar
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 04519d4cf2 | |||
| 88de8c81e7 | |||
| db655bf9db | |||
| aa807060f4 | |||
| 9bbbab9d4b | |||
| 7cca4ada10 | |||
| 725e6df047 | |||
| f3ce124a23 | |||
| e83f72a53e | |||
| def0c19e43 | |||
| 3810ccd63d | |||
| a018af1c8a | |||
| a9fb982143 | |||
| 5b8d881e01 | |||
| eb55f4b395 | |||
| 273db91d06 | |||
| 983ad544c1 | |||
| a6a34b2221 | |||
| 6c6bd19038 | |||
| 89e05cd109 | |||
| ea9d7ac584 | |||
| 17e1cf53b0 | |||
| f64f337f17 | |||
| c5f5be7d58 | |||
| 9f18644763 | |||
| 1de17d27f4 | |||
| 3cd0db9bdf | |||
| 9711b48f2f | |||
|
9934b8bbb2
|
|||
| 6447265b90 | |||
| 71258318db | |||
| 52e95e2649 | |||
| de6ac2cf20 | |||
| 628001e693 | |||
| 47c148d64a | |||
| 78617d5a98 | |||
| 69b924ded6 | |||
| 002f7e5542 | |||
| 5d70f75ac9 |
+11
-10
@@ -21,9 +21,7 @@ package de.steamwar.bausystem.features.design.endstone;
|
|||||||
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
import de.steamwar.bausystem.BauSystem;
|
||||||
import de.steamwar.bausystem.region.Region;
|
import de.steamwar.bausystem.region.Region;
|
||||||
import de.steamwar.entity.REntity;
|
import de.steamwar.entity.*;
|
||||||
import de.steamwar.entity.REntityServer;
|
|
||||||
import de.steamwar.entity.RFallingBlockEntity;
|
|
||||||
import net.md_5.bungee.api.ChatMessageType;
|
import net.md_5.bungee.api.ChatMessageType;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@@ -59,15 +57,15 @@ public class DesignEndStone {
|
|||||||
.filter(material -> material.getBlastResistance() > region.getGameModeConfig().Schematic.MaxDesignBlastResistance)
|
.filter(material -> material.getBlastResistance() > region.getGameModeConfig().Schematic.MaxDesignBlastResistance)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
calculateFromBottom = region.getGameModeConfig().Arena.NoFloor;
|
calculateFromBottom = region.getGameModeConfig().Arena.NoFloor;
|
||||||
|
}
|
||||||
|
|
||||||
entityServer.setCallback((player, rEntity, entityAction) -> {
|
private void interact(Player player, RInteraction entity, REntityAction action) {
|
||||||
if (entityAction != REntityServer.EntityAction.ATTACK) return;
|
if (action != REntityAction.ATTACK) return;
|
||||||
Location location = new Location(WORLD, rEntity.getX(), rEntity.getY(), rEntity.getZ());
|
Location location = new Location(WORLD, entity.getX(), entity.getY(), entity.getZ());
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||||
location.getBlock().breakNaturally();
|
location.getBlock().breakNaturally();
|
||||||
calc();
|
calc();
|
||||||
}, 1);
|
}, 1);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void calc() {
|
public void calc() {
|
||||||
@@ -110,12 +108,15 @@ public class DesignEndStone {
|
|||||||
Material material = WORLD.getBlockAt(cx, cy, cz).getType();
|
Material material = WORLD.getBlockAt(cx, cy, cz).getType();
|
||||||
|
|
||||||
if (material != Material.WATER && material != Material.LAVA && limited.contains(material)) {
|
if (material != Material.WATER && material != Material.LAVA && limited.contains(material)) {
|
||||||
Location location = new Location(WORLD, cx + 0.5, cy, cz + 0.5);
|
Location location = new Location(WORLD, cx, cy, cz);
|
||||||
if (!locations.add(location)) break;
|
if (!locations.add(location)) break;
|
||||||
RFallingBlockEntity entity = new RFallingBlockEntity(entityServer, location, Material.RED_STAINED_GLASS);
|
RBlockDisplay entity = new RBlockDisplay(entityServer, location);
|
||||||
entity.setNoGravity(true);
|
entity.setBlock(Material.RED_STAINED_GLASS.createBlockData());
|
||||||
entity.setGlowing(true);
|
entity.setGlowing(true);
|
||||||
entities.add(entity);
|
entities.add(entity);
|
||||||
|
RInteraction interaction = new RInteraction(entityServer, location);
|
||||||
|
interaction.setCallback(this::interact);
|
||||||
|
entities.add(interaction);
|
||||||
break;
|
break;
|
||||||
} else if (!material.isAir() && material != Material.WATER && material != Material.LAVA) {
|
} else if (!material.isAir() && material != Material.WATER && material != Material.LAVA) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
+10
-9
@@ -26,8 +26,9 @@ import de.steamwar.bausystem.features.autostart.AutostartListener;
|
|||||||
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
|
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
|
||||||
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
|
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
|
||||||
import de.steamwar.core.SWPlayer;
|
import de.steamwar.core.SWPlayer;
|
||||||
|
import de.steamwar.entity.RBlockDisplay;
|
||||||
import de.steamwar.entity.REntityServer;
|
import de.steamwar.entity.REntityServer;
|
||||||
import de.steamwar.entity.RFallingBlockEntity;
|
import de.steamwar.entity.RInteraction;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
@@ -58,10 +59,6 @@ public class Detonator {
|
|||||||
@Override
|
@Override
|
||||||
public void onMount(SWPlayer player) {
|
public void onMount(SWPlayer player) {
|
||||||
entities.addPlayer(player.getPlayer());
|
entities.addPlayer(player.getPlayer());
|
||||||
entities.setCallback((player1, entity, action) -> {
|
|
||||||
Vector vector = new Vector(entity.getX(), entity.getY(), entity.getZ());
|
|
||||||
DetonatorListener.addLocationToDetonator(vector.toLocation(player.getWorld()).getBlock().getLocation(), player1);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,8 +67,6 @@ public class Detonator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Vector HALF = new Vector(0.5, 0, 0.5);
|
|
||||||
|
|
||||||
public static boolean isDetonator(ItemStack itemStack) {
|
public static boolean isDetonator(ItemStack itemStack) {
|
||||||
return ItemStorage.isDetonator(itemStack);
|
return ItemStorage.isDetonator(itemStack);
|
||||||
}
|
}
|
||||||
@@ -79,8 +74,14 @@ public class Detonator {
|
|||||||
public static void showDetonator(Player p, List<Location> locs) {
|
public static void showDetonator(Player p, List<Location> locs) {
|
||||||
DetonatorComponent detonatorComponent = SWPlayer.of(p).getComponentOrDefault(DetonatorComponent.class, DetonatorComponent::new);
|
DetonatorComponent detonatorComponent = SWPlayer.of(p).getComponentOrDefault(DetonatorComponent.class, DetonatorComponent::new);
|
||||||
locs.forEach(location -> {
|
locs.forEach(location -> {
|
||||||
RFallingBlockEntity entity = new RFallingBlockEntity(detonatorComponent.entities, location.clone().add(HALF), Material.RED_STAINED_GLASS);
|
RBlockDisplay blockDisplay = new RBlockDisplay(detonatorComponent.entities, location);
|
||||||
entity.setNoGravity(true);
|
blockDisplay.setBlock(Material.RED_STAINED_GLASS.createBlockData());
|
||||||
|
|
||||||
|
RInteraction interaction = new RInteraction(detonatorComponent.entities, location);
|
||||||
|
interaction.setCallback((player, entity, action) -> {
|
||||||
|
Vector vector = new Vector(entity.getX(), entity.getY(), entity.getZ());
|
||||||
|
DetonatorListener.addLocationToDetonator(vector.toLocation(player.getWorld()).getBlock().getLocation(), player);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -24,9 +24,9 @@ import de.steamwar.bausystem.region.Point;
|
|||||||
import de.steamwar.bausystem.region.Region;
|
import de.steamwar.bausystem.region.Region;
|
||||||
import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar;
|
import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar;
|
||||||
import de.steamwar.bausystem.utils.bossbar.BossBarService;
|
import de.steamwar.bausystem.utils.bossbar.BossBarService;
|
||||||
|
import de.steamwar.entity.RBlockDisplay;
|
||||||
import de.steamwar.entity.REntity;
|
import de.steamwar.entity.REntity;
|
||||||
import de.steamwar.entity.REntityServer;
|
import de.steamwar.entity.REntityServer;
|
||||||
import de.steamwar.entity.RFallingBlockEntity;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@@ -290,8 +290,8 @@ public class KillcheckerVisualizer {
|
|||||||
}
|
}
|
||||||
rEntities.get(point).die();
|
rEntities.get(point).die();
|
||||||
}
|
}
|
||||||
RFallingBlockEntity entity = new RFallingBlockEntity(outlinePoints.contains(point) ? outline : inner, point.toLocation(WORLD, 0.5, 0, 0.5), MATERIALS[Math.min(count - 1, MATERIALS.length) - 1]);
|
RBlockDisplay entity = new RBlockDisplay(outlinePoints.contains(point) ? outline : inner, point.toLocation(WORLD, 0.5, 0, 0.5));
|
||||||
entity.setNoGravity(true);
|
entity.setBlock(MATERIALS[Math.min(count - 1, MATERIALS.length) - 1].createBlockData());
|
||||||
rEntities.put(point, entity);
|
rEntities.put(point, entity);
|
||||||
if (outlinePoints.contains(point)) outlinePointsCache.add(point);
|
if (outlinePoints.contains(point)) outlinePointsCache.add(point);
|
||||||
killCount.put(point, count);
|
killCount.put(point, count);
|
||||||
|
|||||||
+3
-3
@@ -38,7 +38,7 @@ import java.util.Collection;
|
|||||||
public class SimulatorCommand extends SWCommand {
|
public class SimulatorCommand extends SWCommand {
|
||||||
|
|
||||||
@LinkedInstance
|
@LinkedInstance
|
||||||
public SimulatorCursor simulatorCursor;
|
public SimulatorCursorManager simulatorCursorManager;
|
||||||
|
|
||||||
public SimulatorCommand() {
|
public SimulatorCommand() {
|
||||||
super("sim", "simulator");
|
super("sim", "simulator");
|
||||||
@@ -47,12 +47,12 @@ public class SimulatorCommand extends SWCommand {
|
|||||||
@Register(description = "SIMULATOR_HELP")
|
@Register(description = "SIMULATOR_HELP")
|
||||||
public void genericCommand(@Validator Player p) {
|
public void genericCommand(@Validator Player p) {
|
||||||
SWUtils.giveItemToPlayer(p, SimulatorStorage.getWand(p));
|
SWUtils.giveItemToPlayer(p, SimulatorStorage.getWand(p));
|
||||||
simulatorCursor.calcCursor(p);
|
simulatorCursorManager.calcCursor(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Register(value = "change", description = "SIMULATOR_CHANGE_HELP")
|
@Register(value = "change", description = "SIMULATOR_CHANGE_HELP")
|
||||||
public void change(@Validator Player p) {
|
public void change(@Validator Player p) {
|
||||||
if (!SimulatorCursor.isSimulatorItem(p.getInventory().getItemInMainHand()) && !SimulatorCursor.isSimulatorItem(p.getInventory().getItemInOffHand())) {
|
if (!SimulatorCursorManager.isSimulatorItem(p.getInventory().getItemInMainHand()) && !SimulatorCursorManager.isSimulatorItem(p.getInventory().getItemInOffHand())) {
|
||||||
BauSystem.MESSAGE.send("SIMULATOR_NO_SIM_IN_HAND", p);
|
BauSystem.MESSAGE.send("SIMULATOR_NO_SIM_IN_HAND", p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
-468
@@ -1,468 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is a part of the SteamWar software.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.bausystem.features.simulator;
|
|
||||||
|
|
||||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
|
||||||
import de.steamwar.bausystem.BauSystem;
|
|
||||||
import de.steamwar.bausystem.Permission;
|
|
||||||
import de.steamwar.bausystem.SWUtils;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.observer.ObserverPhase;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.redstone.RedstoneElement;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.redstone.RedstonePhase;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
|
|
||||||
import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase;
|
|
||||||
import de.steamwar.bausystem.features.simulator.execute.SimulatorExecutor;
|
|
||||||
import de.steamwar.bausystem.features.simulator.gui.SimulatorGroupGui;
|
|
||||||
import de.steamwar.bausystem.features.simulator.gui.SimulatorGui;
|
|
||||||
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
|
|
||||||
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
|
|
||||||
import de.steamwar.bausystem.utils.ItemUtils;
|
|
||||||
import de.steamwar.bausystem.utils.RayTraceUtils;
|
|
||||||
import de.steamwar.entity.REntity;
|
|
||||||
import de.steamwar.entity.REntityServer;
|
|
||||||
import de.steamwar.entity.RFallingBlockEntity;
|
|
||||||
import de.steamwar.inventory.SWAnvilInv;
|
|
||||||
import de.steamwar.linkage.Linked;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.block.Action;
|
|
||||||
import org.bukkit.event.player.*;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Linked
|
|
||||||
public class SimulatorCursor implements Listener {
|
|
||||||
|
|
||||||
private static final World WORLD = Bukkit.getWorlds().get(0);
|
|
||||||
|
|
||||||
private static Map<Player, CursorType> cursorType = Collections.synchronizedMap(new HashMap<>());
|
|
||||||
private static Map<Player, REntityServer> cursors = Collections.synchronizedMap(new HashMap<>());
|
|
||||||
private static final Set<Player> calculating = new HashSet<>();
|
|
||||||
|
|
||||||
public static boolean isSimulatorItem(ItemStack itemStack) {
|
|
||||||
return ItemUtils.isItem(itemStack, "simulator");
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimulatorCursor() {
|
|
||||||
BiFunction<Player, ServerboundMovePlayerPacket, Object> function = (player, object) -> {
|
|
||||||
calcCursor(player);
|
|
||||||
return object;
|
|
||||||
};
|
|
||||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Pos.class, function);
|
|
||||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Rot.class, function);
|
|
||||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.PosRot.class, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
|
||||||
calcCursor(event.getPlayer());
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
|
||||||
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
|
||||||
calcCursor(event.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerItemHeld(PlayerItemHeldEvent event) {
|
|
||||||
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
|
||||||
calcCursor(event.getPlayer());
|
|
||||||
}, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
|
||||||
event.getChanged().forEach(SimulatorCursor::calcCursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
cursorType.remove(event.getPlayer());
|
|
||||||
cursors.remove(event.getPlayer());
|
|
||||||
synchronized (calculating) {
|
|
||||||
calculating.remove(event.getPlayer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Player, Long> LAST_SNEAKS = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
|
|
||||||
long millis = System.currentTimeMillis();
|
|
||||||
LAST_SNEAKS.entrySet().removeIf(entry -> millis - entry.getValue() > 200);
|
|
||||||
}, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH)
|
|
||||||
public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
|
|
||||||
if (!event.isSneaking()) return;
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
if (!isSimulatorItem(player.getInventory().getItemInMainHand()) && !isSimulatorItem(player.getInventory().getItemInOffHand())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (LAST_SNEAKS.containsKey(player)) {
|
|
||||||
CursorType currentType = cursorType.getOrDefault(player, CursorType.TNT);
|
|
||||||
if (currentType == CursorType.TNT) {
|
|
||||||
cursorType.put(player, CursorType.REDSTONE_BLOCK);
|
|
||||||
} else {
|
|
||||||
cursorType.put(player, CursorType.TNT);
|
|
||||||
}
|
|
||||||
calcCursor(player);
|
|
||||||
} else {
|
|
||||||
LAST_SNEAKS.put(player, System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CursorType getCursorType(Player player) {
|
|
||||||
return cursorType.getOrDefault(player, CursorType.TNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setCursorType(Player player, CursorType cursorType) {
|
|
||||||
SimulatorCursor.cursorType.put(player, cursorType);
|
|
||||||
calcCursor(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void calcCursor(Player player) {
|
|
||||||
synchronized (calculating) {
|
|
||||||
if (calculating.contains(player)) return;
|
|
||||||
calculating.add(player);
|
|
||||||
}
|
|
||||||
if (!Permission.BUILD.hasPermission(player) || (!isSimulatorItem(player.getInventory().getItemInMainHand()) && !isSimulatorItem(player.getInventory().getItemInOffHand()))) {
|
|
||||||
if (removeCursor(player) || SimulatorWatcher.show(null, player)) {
|
|
||||||
SWUtils.sendToActionbar(player, "");
|
|
||||||
}
|
|
||||||
synchronized (calculating) {
|
|
||||||
calculating.remove(player);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Simulator simulator = SimulatorStorage.getSimulator(player);
|
|
||||||
if (simulator != null && simulator.getStabGenerator() != null) {
|
|
||||||
removeCursor(player);
|
|
||||||
SimulatorWatcher.show(null, player);
|
|
||||||
SWUtils.sendToActionbar(player, "§cGenerating Stab");
|
|
||||||
synchronized (calculating) {
|
|
||||||
calculating.remove(player);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SimulatorWatcher.show(simulator, player);
|
|
||||||
List<REntity> entities = SimulatorWatcher.getEntitiesOfSimulator(simulator);
|
|
||||||
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(player, player.getLocation(), entities);
|
|
||||||
if (rayTraceResult == null) {
|
|
||||||
removeCursor(player);
|
|
||||||
if (simulator == null) {
|
|
||||||
SWUtils.sendToActionbar(player, "§eSelect Simulator");
|
|
||||||
} else {
|
|
||||||
SWUtils.sendToActionbar(player, "§eOpen Simulator");
|
|
||||||
}
|
|
||||||
synchronized (calculating) {
|
|
||||||
calculating.remove(player);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
showCursor(player, rayTraceResult, simulator != null);
|
|
||||||
synchronized (calculating) {
|
|
||||||
calculating.remove(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static synchronized boolean removeCursor(Player player) {
|
|
||||||
REntityServer entityServer = cursors.get(player);
|
|
||||||
boolean hadCursor = entityServer != null && !entityServer.getEntities().isEmpty();
|
|
||||||
if (entityServer != null) {
|
|
||||||
entityServer.getEntities().forEach(REntity::die);
|
|
||||||
}
|
|
||||||
return hadCursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static synchronized void showCursor(Player player, RayTraceUtils.RRayTraceResult rayTraceResult, boolean hasSimulatorSelected) {
|
|
||||||
REntityServer entityServer = cursors.computeIfAbsent(player, __ -> {
|
|
||||||
REntityServer rEntityServer = new REntityServer();
|
|
||||||
rEntityServer.addPlayer(player);
|
|
||||||
return rEntityServer;
|
|
||||||
});
|
|
||||||
|
|
||||||
CursorType type = cursorType.getOrDefault(player, CursorType.TNT);
|
|
||||||
REntity hitEntity = rayTraceResult.getHitEntity();
|
|
||||||
Location location = hitEntity != null ? new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ()).toLocation(WORLD) :
|
|
||||||
type.position.apply(player, rayTraceResult).toLocation(WORLD);
|
|
||||||
|
|
||||||
Material material = hitEntity != null ? Material.GLASS : type.getMaterial();
|
|
||||||
List<RFallingBlockEntity> entities = entityServer.getEntitiesByType(RFallingBlockEntity.class);
|
|
||||||
entities.removeIf(rFallingBlockEntity -> {
|
|
||||||
if (rFallingBlockEntity.getMaterial() != material) {
|
|
||||||
rFallingBlockEntity.die();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
rFallingBlockEntity.move(location);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if (entities.isEmpty()) {
|
|
||||||
RFallingBlockEntity rFallingBlockEntity = new RFallingBlockEntity(entityServer, location, material);
|
|
||||||
rFallingBlockEntity.setNoGravity(true);
|
|
||||||
if (material == Material.GLASS) {
|
|
||||||
rFallingBlockEntity.setGlowing(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasSimulatorSelected) {
|
|
||||||
if (hitEntity != null) {
|
|
||||||
SWUtils.sendToActionbar(player, "§eEdit Position");
|
|
||||||
} else {
|
|
||||||
SWUtils.sendToActionbar(player, "§eAdd new " + type.name);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SWUtils.sendToActionbar(player, "§eCreate new Simulator");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vector getPosFree(Player player, RayTraceUtils.RRayTraceResult result) {
|
|
||||||
Vector pos = result.getHitPosition();
|
|
||||||
|
|
||||||
BlockFace face = result.getHitBlockFace();
|
|
||||||
if (face != null) {
|
|
||||||
switch (face) {
|
|
||||||
case DOWN:
|
|
||||||
pos.setY(pos.getY() - 0.98);
|
|
||||||
break;
|
|
||||||
case EAST:
|
|
||||||
pos.setX(pos.getX() + 0.49);
|
|
||||||
break;
|
|
||||||
case WEST:
|
|
||||||
pos.setX(pos.getX() - 0.49);
|
|
||||||
break;
|
|
||||||
case NORTH:
|
|
||||||
pos.setZ(pos.getZ() - 0.49);
|
|
||||||
break;
|
|
||||||
case SOUTH:
|
|
||||||
pos.setZ(pos.getZ() + 0.49);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (face.getModY() == 0 && player.isSneaking()) {
|
|
||||||
pos.setY(pos.getY() - 0.49);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.isSneaking()) {
|
|
||||||
pos.setX(pos.getBlockX() + 0.5);
|
|
||||||
if (face == null || face.getModY() == 0) {
|
|
||||||
pos.setY(pos.getBlockY() + 0.0);
|
|
||||||
}
|
|
||||||
pos.setZ(pos.getBlockZ() + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Vector getPosBlockAligned(Player player, RayTraceUtils.RRayTraceResult result) {
|
|
||||||
Vector pos = result.getHitPosition();
|
|
||||||
|
|
||||||
BlockFace face = result.getHitBlockFace();
|
|
||||||
if (face != null) {
|
|
||||||
switch (face) {
|
|
||||||
case DOWN:
|
|
||||||
pos.setY(pos.getY() - 0.98);
|
|
||||||
break;
|
|
||||||
case EAST:
|
|
||||||
pos.setX(pos.getX() + 0.49);
|
|
||||||
break;
|
|
||||||
case WEST:
|
|
||||||
pos.setX(pos.getX() - 0.49);
|
|
||||||
break;
|
|
||||||
case NORTH:
|
|
||||||
pos.setZ(pos.getZ() - 0.49);
|
|
||||||
break;
|
|
||||||
case SOUTH:
|
|
||||||
pos.setZ(pos.getZ() + 0.49);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pos.setX(pos.getBlockX() + 0.5);
|
|
||||||
if (pos.getY() - pos.getBlockY() != 0 && face == BlockFace.UP) {
|
|
||||||
pos.setY(pos.getBlockY() + 1.0);
|
|
||||||
} else {
|
|
||||||
pos.setY(pos.getBlockY());
|
|
||||||
}
|
|
||||||
pos.setZ(pos.getBlockZ() + 0.5);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum CursorType {
|
|
||||||
TNT(Material.TNT, Material.GUNPOWDER, SimulatorCursor::getPosFree, "TNT", vector -> new TNTElement(vector).add(new TNTPhase())),
|
|
||||||
REDSTONE_BLOCK(Material.REDSTONE_BLOCK, Material.REDSTONE, SimulatorCursor::getPosBlockAligned, "Redstone Block", vector -> new RedstoneElement(vector).add(new RedstonePhase())),
|
|
||||||
OBSERVER(Material.OBSERVER, Material.QUARTZ, SimulatorCursor::getPosBlockAligned, "Observer", vector -> new ObserverElement(vector).add(new ObserverPhase())),
|
|
||||||
;
|
|
||||||
|
|
||||||
public final Material material;
|
|
||||||
public final Material nonSelectedMaterial;
|
|
||||||
public final BiFunction<Player, RayTraceUtils.RRayTraceResult, Vector> position;
|
|
||||||
public final String name;
|
|
||||||
public final Function<Vector, SimulatorElement<?>> elementFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
|
||||||
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
|
||||||
if (!ItemUtils.isItem(event.getItem(), "simulator")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.setCancelled(true);
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
Simulator simulator = SimulatorStorage.getSimulator(player);
|
|
||||||
|
|
||||||
if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR) {
|
|
||||||
if (simulator == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SimulatorExecutor.run(event.getPlayer(), simulator, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(player, player.getLocation(), SimulatorWatcher.getEntitiesOfSimulator(simulator));
|
|
||||||
if (simulator == null) {
|
|
||||||
if (rayTraceResult == null) {
|
|
||||||
SimulatorStorage.openSimulatorSelector(player);
|
|
||||||
} else {
|
|
||||||
SWAnvilInv anvilInv = new SWAnvilInv(player, "Name");
|
|
||||||
anvilInv.setCallback(s -> {
|
|
||||||
Simulator sim = SimulatorStorage.getSimulator(s);
|
|
||||||
if (sim != null) {
|
|
||||||
BauSystem.MESSAGE.send("SIMULATOR_NAME_ALREADY_EXISTS", player);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!s.matches("[a-zA-Z_0-9-]+")) {
|
|
||||||
BauSystem.MESSAGE.send("SIMULATOR_NAME_INVALID", player);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sim = new Simulator(s);
|
|
||||||
SimulatorStorage.addSimulator(s, sim);
|
|
||||||
createElement(player, rayTraceResult, sim);
|
|
||||||
SimulatorStorage.setSimulator(player, sim);
|
|
||||||
});
|
|
||||||
anvilInv.open();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rayTraceResult == null) {
|
|
||||||
new SimulatorGui(player, simulator).open();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rayTraceResult.getHitEntity() != null) {
|
|
||||||
REntity hitEntity = rayTraceResult.getHitEntity();
|
|
||||||
Vector vector = new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ());
|
|
||||||
List<SimulatorElement<?>> elements = simulator.getGroups().stream().map(SimulatorGroup::getElements).flatMap(List::stream).filter(element -> {
|
|
||||||
return element.getWorldPos().distanceSquared(vector) < (1 / 16.0) * (1 / 16.0);
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
switch (elements.size()) {
|
|
||||||
case 0:
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
// Open single element present in Simulator
|
|
||||||
SimulatorElement<?> element = elements.get(0);
|
|
||||||
SimulatorGroup group1 = element.getGroup(simulator);
|
|
||||||
SimulatorBaseGui back = new SimulatorGui(player, simulator);
|
|
||||||
if (group1.getElements().size() > 1) {
|
|
||||||
back = new SimulatorGroupGui(player, simulator, group1, back);
|
|
||||||
}
|
|
||||||
element.open(player, simulator, group1, back);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
List<SimulatorGroup> parents = elements.stream().map(e -> e.getGroup(simulator)).distinct().collect(Collectors.toList());
|
|
||||||
if (parents.size() == 1) {
|
|
||||||
// Open multi element present in Simulator in existing group
|
|
||||||
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
|
|
||||||
new SimulatorGroupGui(player, simulator, parents.get(0), simulatorGui).open();
|
|
||||||
} else {
|
|
||||||
// Open multi element present in Simulator in implicit group
|
|
||||||
SimulatorGroup group2 = new SimulatorGroup();
|
|
||||||
group2.setMaterial(null);
|
|
||||||
group2.getElements().addAll(elements);
|
|
||||||
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
|
|
||||||
new SimulatorGroupGui(player, simulator, group2, simulatorGui).open();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new Element to current simulator
|
|
||||||
createElement(player, rayTraceResult, simulator);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createElement(Player player, RayTraceUtils.RRayTraceResult rayTraceResult, Simulator simulator) {
|
|
||||||
CursorType type = cursorType.getOrDefault(player, CursorType.TNT);
|
|
||||||
Vector vector = type.position.apply(player, rayTraceResult);
|
|
||||||
if (type == CursorType.REDSTONE_BLOCK) {
|
|
||||||
vector.subtract(new Vector(0.5, 0, 0.5));
|
|
||||||
}
|
|
||||||
SimulatorElement<?> element = type.elementFunction.apply(vector);
|
|
||||||
SimulatorGroup group = new SimulatorGroup().add(element);
|
|
||||||
simulator.getGroups().add(group);
|
|
||||||
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
|
|
||||||
element.open(player, simulator, group, simulatorGui);
|
|
||||||
SimulatorWatcher.update(simulator);
|
|
||||||
calcCursor(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+440
@@ -0,0 +1,440 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.bausystem.features.simulator;
|
||||||
|
|
||||||
|
import de.steamwar.bausystem.BauSystem;
|
||||||
|
import de.steamwar.bausystem.Permission;
|
||||||
|
import de.steamwar.bausystem.SWUtils;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.observer.ObserverPhase;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.redstone.RedstoneElement;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.redstone.RedstonePhase;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
|
||||||
|
import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase;
|
||||||
|
import de.steamwar.bausystem.features.simulator.execute.SimulatorExecutor;
|
||||||
|
import de.steamwar.bausystem.features.simulator.gui.SimulatorGroupGui;
|
||||||
|
import de.steamwar.bausystem.features.simulator.gui.SimulatorGui;
|
||||||
|
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
|
||||||
|
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
|
||||||
|
import de.steamwar.bausystem.utils.ItemUtils;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
|
import de.steamwar.cursor.Cursor;
|
||||||
|
import de.steamwar.entity.REntity;
|
||||||
|
import de.steamwar.entity.REntityServer;
|
||||||
|
import de.steamwar.inventory.SWAnvilInv;
|
||||||
|
import de.steamwar.linkage.Linked;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||||
|
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.event.player.PlayerToggleSneakEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Linked
|
||||||
|
public class SimulatorCursorManager implements Listener {
|
||||||
|
|
||||||
|
private static class SimulatorCursorComponent implements SWPlayer.Component {
|
||||||
|
private Player player;
|
||||||
|
private Cursor cursor;
|
||||||
|
private CursorType cursorType = CursorType.TNT;
|
||||||
|
private REntityServer emptyTargetServer;
|
||||||
|
private REntityServer currentTargetServer;
|
||||||
|
private long lastSneakMillis;
|
||||||
|
|
||||||
|
private SimulatorCursorComponent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private SimulatorCursorComponent(CursorType cursorType) {
|
||||||
|
this.cursorType = cursorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private REntityServer getOrCreateEmptyTargetServer() {
|
||||||
|
if (emptyTargetServer == null) {
|
||||||
|
emptyTargetServer = new REntityServer();
|
||||||
|
}
|
||||||
|
return emptyTargetServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handleSneak(long now) {
|
||||||
|
boolean doubleSneak = now - lastSneakMillis <= 200;
|
||||||
|
lastSneakMillis = doubleSneak ? 0 : now;
|
||||||
|
return doubleSneak;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CursorType getCursorType() {
|
||||||
|
return cursorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCursorType(CursorType cursorType) {
|
||||||
|
this.cursorType = cursorType;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchCursorMode() {
|
||||||
|
cursorType = cursorType == CursorType.TNT ? CursorType.REDSTONE_BLOCK : CursorType.TNT;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refresh() {
|
||||||
|
if (!Permission.BUILD.hasPermission(player) || !hasSimulatorItem(player)) {
|
||||||
|
deactivateCursor(player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Simulator simulator = SimulatorStorage.getSimulator(player);
|
||||||
|
if (simulator != null && simulator.getStabGenerator() != null) {
|
||||||
|
removeGenericCursor();
|
||||||
|
boolean watcherRemoved = SimulatorWatcher.show(null, player);
|
||||||
|
if (watcherRemoved) {
|
||||||
|
SWUtils.sendToActionbar(player, "");
|
||||||
|
}
|
||||||
|
SWUtils.sendToActionbar(player, "§cGenerating Stab");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimulatorWatcher.show(simulator, player);
|
||||||
|
REntityServer targetServer = simulator == null ? getOrCreateEmptyTargetServer() : SimulatorWatcher.getEntityServerOfSimulator(simulator);
|
||||||
|
if (cursor == null || currentTargetServer != targetServer) {
|
||||||
|
removeGenericCursor();
|
||||||
|
currentTargetServer = targetServer;
|
||||||
|
cursor = new Cursor(
|
||||||
|
targetServer,
|
||||||
|
player,
|
||||||
|
Material.GLASS,
|
||||||
|
cursorType.material,
|
||||||
|
cursorType.cursorModes,
|
||||||
|
this::handlePlayerClick,
|
||||||
|
(location, hitEntity) -> sendCursorActionbar(simulator, location != null, hitEntity.isPresent())
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cursor.setCursorMaterial(cursorType.material);
|
||||||
|
cursor.setAllowedCursorModes(cursorType.cursorModes);
|
||||||
|
}
|
||||||
|
cursor.renderDeduplicated();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeGenericCursor() {
|
||||||
|
if (cursor == null && !SWPlayer.of(player).hasComponent(Cursor.class)) {
|
||||||
|
currentTargetServer = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWPlayer.of(player).removeComponent(Cursor.class);
|
||||||
|
cursor = null;
|
||||||
|
currentTargetServer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeEmptyTargetServer() {
|
||||||
|
if (emptyTargetServer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyTargetServer.close();
|
||||||
|
emptyTargetServer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendCursorActionbar(Simulator simulator, boolean hasCursorLocation, boolean hasHitEntity) {
|
||||||
|
if (!hasCursorLocation) {
|
||||||
|
SWUtils.sendToActionbar(player, simulator == null ? "§eSelect Simulator" : "§eOpen Simulator");
|
||||||
|
} else if (simulator == null) {
|
||||||
|
SWUtils.sendToActionbar(player, "§eCreate new Simulator");
|
||||||
|
} else if (hasHitEntity) {
|
||||||
|
SWUtils.sendToActionbar(player, "§eEdit Position");
|
||||||
|
} else {
|
||||||
|
SWUtils.sendToActionbar(player, "§eAdd new " + cursorType.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handlePlayerClick(Location cursorLocation, Optional<REntity> hitEntity, Action action) {
|
||||||
|
if (!Permission.BUILD.hasPermission(player)) return;
|
||||||
|
if (!hasSimulatorItem(player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Simulator simulator = SimulatorStorage.getSimulator(player);
|
||||||
|
|
||||||
|
if (action == Action.LEFT_CLICK_BLOCK || action == Action.LEFT_CLICK_AIR) {
|
||||||
|
if (simulator == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SimulatorExecutor.run(player, simulator, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action != Action.RIGHT_CLICK_BLOCK && action != Action.RIGHT_CLICK_AIR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (simulator == null) {
|
||||||
|
if (cursorLocation == null) {
|
||||||
|
SimulatorStorage.openSimulatorSelector(player);
|
||||||
|
} else {
|
||||||
|
SWAnvilInv anvilInv = new SWAnvilInv(player, "Name");
|
||||||
|
anvilInv.setCallback(s -> {
|
||||||
|
Simulator sim = SimulatorStorage.getSimulator(s);
|
||||||
|
if (sim != null) {
|
||||||
|
BauSystem.MESSAGE.send("SIMULATOR_NAME_ALREADY_EXISTS", player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!s.matches("[a-zA-Z_0-9-]+")) {
|
||||||
|
BauSystem.MESSAGE.send("SIMULATOR_NAME_INVALID", player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sim = new Simulator(s);
|
||||||
|
SimulatorStorage.addSimulator(s, sim);
|
||||||
|
createElement(player, cursorLocation, sim);
|
||||||
|
SimulatorStorage.setSimulator(player, sim);
|
||||||
|
});
|
||||||
|
anvilInv.open();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursorLocation == null) {
|
||||||
|
new SimulatorGui(player, simulator).open();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitEntity.isPresent()) {
|
||||||
|
openElement(player, simulator, hitEntity.get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
createElement(player, cursorLocation, simulator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMount(SWPlayer player) {
|
||||||
|
this.player = player.getPlayer();
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnmount(SWPlayer player) {
|
||||||
|
boolean hadCursor = cursor != null || player.hasComponent(Cursor.class);
|
||||||
|
removeGenericCursor();
|
||||||
|
closeEmptyTargetServer();
|
||||||
|
boolean watcherRemoved = SimulatorWatcher.show(null, this.player);
|
||||||
|
if (hadCursor || watcherRemoved) {
|
||||||
|
SWUtils.sendToActionbar(this.player, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSimulatorItem(ItemStack itemStack) {
|
||||||
|
return ItemUtils.isItem(itemStack, "simulator");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasSimulatorItem(Player player) {
|
||||||
|
return isSimulatorItem(player.getInventory().getItemInMainHand()) || isSimulatorItem(player.getInventory().getItemInOffHand());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||||
|
if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
|
||||||
|
calcCursor(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerItemHeld(PlayerItemHeldEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (!Permission.BUILD.hasPermission(player)) return;
|
||||||
|
|
||||||
|
boolean hasSimulatorInNewMainHand = isSimulatorItem(player.getInventory().getItem(event.getNewSlot()));
|
||||||
|
boolean hasSimulatorInOffHand = isSimulatorItem(player.getInventory().getItemInOffHand());
|
||||||
|
if (!hasSimulatorInNewMainHand && !hasSimulatorInOffHand) {
|
||||||
|
boolean cursorRemoved = deactivateCursor(player);
|
||||||
|
boolean watcherRemoved = SimulatorWatcher.show(null, player);
|
||||||
|
if (cursorRemoved || watcherRemoved) {
|
||||||
|
SWUtils.sendToActionbar(player, "");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> calcCursor(player), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
||||||
|
event.getChanged().forEach(SimulatorCursorManager::calcCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
deactivateCursor(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
|
public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
|
||||||
|
if (!event.isSneaking()) return;
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (!hasSimulatorItem(player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SimulatorCursorComponent component = activateOrRefresh(player);
|
||||||
|
if (component == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean shouldSwitch = component.handleSneak(System.currentTimeMillis());
|
||||||
|
if (shouldSwitch) {
|
||||||
|
component.switchCursorMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CursorType getCursorType(Player player) {
|
||||||
|
return SWPlayer.of(player).getComponent(SimulatorCursorComponent.class)
|
||||||
|
.map(SimulatorCursorComponent::getCursorType)
|
||||||
|
.orElse(CursorType.TNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCursorType(Player player, CursorType cursorType) {
|
||||||
|
Optional<SimulatorCursorComponent> component = SWPlayer.of(player).getComponent(SimulatorCursorComponent.class);
|
||||||
|
if (component.isPresent()) {
|
||||||
|
component.get().setCursorType(cursorType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Permission.BUILD.hasPermission(player) || !hasSimulatorItem(player)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SWPlayer.of(player).setComponent(new SimulatorCursorComponent(cursorType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void calcCursor(Player player) {
|
||||||
|
activateOrRefresh(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SimulatorCursorComponent activateOrRefresh(Player player) {
|
||||||
|
if (!Permission.BUILD.hasPermission(player) || !hasSimulatorItem(player)) {
|
||||||
|
boolean cursorRemoved = deactivateCursor(player);
|
||||||
|
boolean watcherRemoved = SimulatorWatcher.show(null, player);
|
||||||
|
if (cursorRemoved || watcherRemoved) {
|
||||||
|
SWUtils.sendToActionbar(player, "");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWPlayer swPlayer = SWPlayer.of(player);
|
||||||
|
Optional<SimulatorCursorComponent> existingComponent = swPlayer.getComponent(SimulatorCursorComponent.class);
|
||||||
|
if (existingComponent.isPresent()) {
|
||||||
|
SimulatorCursorComponent component = existingComponent.get();
|
||||||
|
component.refresh();
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimulatorCursorComponent component = new SimulatorCursorComponent();
|
||||||
|
swPlayer.setComponent(component);
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static synchronized boolean deactivateCursor(Player player) {
|
||||||
|
SWPlayer swPlayer = SWPlayer.of(player);
|
||||||
|
boolean hadSimulatorCursor = swPlayer.hasComponent(SimulatorCursorComponent.class);
|
||||||
|
boolean hadCursor = swPlayer.hasComponent(Cursor.class);
|
||||||
|
swPlayer.removeComponent(SimulatorCursorComponent.class);
|
||||||
|
if (!hadSimulatorCursor) {
|
||||||
|
swPlayer.removeComponent(Cursor.class);
|
||||||
|
}
|
||||||
|
return hadSimulatorCursor || hadCursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum CursorType {
|
||||||
|
TNT(Material.TNT, Material.GUNPOWDER, List.of(Cursor.CursorMode.SURFACE_ALIGNED, Cursor.CursorMode.FREE), "TNT", vector -> new TNTElement(vector).add(new TNTPhase())),
|
||||||
|
REDSTONE_BLOCK(Material.REDSTONE_BLOCK, Material.REDSTONE, List.of(Cursor.CursorMode.BLOCK_ALIGNED), "Redstone Block", vector -> new RedstoneElement(vector).add(new RedstonePhase())),
|
||||||
|
OBSERVER(Material.OBSERVER, Material.QUARTZ, List.of(Cursor.CursorMode.BLOCK_ALIGNED), "Observer", vector -> new ObserverElement(vector).add(new ObserverPhase())),
|
||||||
|
;
|
||||||
|
|
||||||
|
public final Material material;
|
||||||
|
public final Material nonSelectedMaterial;
|
||||||
|
public final List<Cursor.CursorMode> cursorModes;
|
||||||
|
public final String name;
|
||||||
|
public final Function<Vector, SimulatorElement<?>> elementFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void openElement(Player player, Simulator simulator, REntity hitEntity) {
|
||||||
|
Vector vector = new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ());
|
||||||
|
List<SimulatorElement<?>> elements = simulator.getGroups().stream().map(SimulatorGroup::getElements).flatMap(List::stream).filter(element -> {
|
||||||
|
return element.getWorldPos().distanceSquared(vector) < (1 / 16.0) * (1 / 16.0);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
switch (elements.size()) {
|
||||||
|
case 0:
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
SimulatorElement<?> element = elements.get(0);
|
||||||
|
SimulatorGroup group1 = element.getGroup(simulator);
|
||||||
|
SimulatorBaseGui back = new SimulatorGui(player, simulator);
|
||||||
|
if (group1.getElements().size() > 1) {
|
||||||
|
back = new SimulatorGroupGui(player, simulator, group1, back);
|
||||||
|
}
|
||||||
|
element.open(player, simulator, group1, back);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
List<SimulatorGroup> parents = elements.stream().map(e -> e.getGroup(simulator)).distinct().collect(Collectors.toList());
|
||||||
|
if (parents.size() == 1) {
|
||||||
|
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
|
||||||
|
new SimulatorGroupGui(player, simulator, parents.get(0), simulatorGui).open();
|
||||||
|
} else {
|
||||||
|
SimulatorGroup group2 = new SimulatorGroup();
|
||||||
|
group2.setMaterial(null);
|
||||||
|
group2.getElements().addAll(elements);
|
||||||
|
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
|
||||||
|
new SimulatorGroupGui(player, simulator, group2, simulatorGui).open();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createElement(Player player, Location cursorLocation, Simulator simulator) {
|
||||||
|
CursorType type = getCursorType(player);
|
||||||
|
Vector vector = cursorLocation.toVector();
|
||||||
|
if (type == CursorType.REDSTONE_BLOCK) {
|
||||||
|
vector.subtract(new Vector(0.5, 0, 0.5));
|
||||||
|
}
|
||||||
|
SimulatorElement<?> element = type.elementFunction.apply(vector);
|
||||||
|
SimulatorGroup group = new SimulatorGroup().add(element);
|
||||||
|
simulator.getGroups().add(group);
|
||||||
|
SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
|
||||||
|
element.open(player, simulator, group, simulatorGui);
|
||||||
|
SimulatorWatcher.update(simulator);
|
||||||
|
calcCursor(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -59,7 +59,7 @@ public class SimulatorStorage implements Enable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Simulator getSimulator(ItemStack itemStack) {
|
public static Simulator getSimulator(ItemStack itemStack) {
|
||||||
if (!SimulatorCursor.isSimulatorItem(itemStack)) {
|
if (!SimulatorCursorManager.isSimulatorItem(itemStack)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String selection = ItemUtils.getTag(itemStack, simulatorSelection);
|
String selection = ItemUtils.getTag(itemStack, simulatorSelection);
|
||||||
@@ -181,9 +181,9 @@ public class SimulatorStorage implements Enable {
|
|||||||
ItemStack mainHand = player.getInventory().getItemInMainHand();
|
ItemStack mainHand = player.getInventory().getItemInMainHand();
|
||||||
ItemStack offHand = player.getInventory().getItemInOffHand();
|
ItemStack offHand = player.getInventory().getItemInOffHand();
|
||||||
ItemStack itemStack;
|
ItemStack itemStack;
|
||||||
if (SimulatorCursor.isSimulatorItem(mainHand)) {
|
if (SimulatorCursorManager.isSimulatorItem(mainHand)) {
|
||||||
itemStack = mainHand;
|
itemStack = mainHand;
|
||||||
} else if (SimulatorCursor.isSimulatorItem(offHand)) {
|
} else if (SimulatorCursorManager.isSimulatorItem(offHand)) {
|
||||||
itemStack = offHand;
|
itemStack = offHand;
|
||||||
} else {
|
} else {
|
||||||
itemStack = null;
|
itemStack = null;
|
||||||
|
|||||||
+7
@@ -124,4 +124,11 @@ public class SimulatorWatcher {
|
|||||||
}
|
}
|
||||||
return entityServer.getEntities();
|
return entityServer.getEntities();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized REntityServer getEntityServerOfSimulator(Simulator simulator) {
|
||||||
|
if (simulator == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return entityServers.computeIfAbsent(simulator, __ -> createSim(new REntityServer(), simulator));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.bausystem.features.simulator.gui;
|
package de.steamwar.bausystem.features.simulator.gui;
|
||||||
|
|
||||||
import de.steamwar.bausystem.features.simulator.SimulatorCursor;
|
import de.steamwar.bausystem.features.simulator.SimulatorCursorManager;
|
||||||
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
||||||
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
|
import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
|
||||||
import de.steamwar.data.CMDs;
|
import de.steamwar.data.CMDs;
|
||||||
@@ -50,14 +50,14 @@ public class SimulatorCursorSwitcherGui extends SimulatorBaseGui {
|
|||||||
}).setCustomModelData(CMDs.BACK));
|
}).setCustomModelData(CMDs.BACK));
|
||||||
|
|
||||||
int slot = 2;
|
int slot = 2;
|
||||||
SimulatorCursor.CursorType currentType = SimulatorCursor.getCursorType(player);
|
SimulatorCursorManager.CursorType currentType = SimulatorCursorManager.getCursorType(player);
|
||||||
for (SimulatorCursor.CursorType type : SimulatorCursor.CursorType.values()) {
|
for (SimulatorCursorManager.CursorType type : SimulatorCursorManager.CursorType.values()) {
|
||||||
boolean selected = type == currentType;
|
boolean selected = type == currentType;
|
||||||
SWItem swItem = new SWItem(selected ? type.material : type.nonSelectedMaterial, "§e" + type.name)
|
SWItem swItem = new SWItem(selected ? type.material : type.nonSelectedMaterial, "§e" + type.name)
|
||||||
.setCustomModelData(selected ? 0 : CMDs.Simulator.NEW_PHASE)
|
.setCustomModelData(selected ? 0 : CMDs.Simulator.NEW_PHASE)
|
||||||
.setLore(Collections.singletonList("§eClick to select"))
|
.setLore(Collections.singletonList("§eClick to select"))
|
||||||
.setCallback(click -> {
|
.setCallback(click -> {
|
||||||
SimulatorCursor.setCursorType(player, type);
|
SimulatorCursorManager.setCursorType(player, type);
|
||||||
player.closeInventory();
|
player.closeInventory();
|
||||||
});
|
});
|
||||||
inventory.setItem(slot, swItem);
|
inventory.setItem(slot, swItem);
|
||||||
|
|||||||
+2
-2
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.bausystem.features.simulator.gui;
|
package de.steamwar.bausystem.features.simulator.gui;
|
||||||
|
|
||||||
import de.steamwar.bausystem.features.simulator.SimulatorCursor;
|
import de.steamwar.bausystem.features.simulator.SimulatorCursorManager;
|
||||||
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
|
import de.steamwar.bausystem.features.simulator.SimulatorWatcher;
|
||||||
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
||||||
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
|
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
|
||||||
@@ -50,7 +50,7 @@ public class SimulatorGui extends SimulatorPageGui<SimulatorGroup> {
|
|||||||
inventory.setItem(4, simulator.toItem(player, clickType -> {
|
inventory.setItem(4, simulator.toItem(player, clickType -> {
|
||||||
new SimulatorMaterialGui(player, simulator, simulator::getMaterial, simulator::setMaterial, this).open();
|
new SimulatorMaterialGui(player, simulator, simulator::getMaterial, simulator::setMaterial, this).open();
|
||||||
}));
|
}));
|
||||||
SimulatorCursor.CursorType cursorType = SimulatorCursor.getCursorType(player);
|
SimulatorCursorManager.CursorType cursorType = SimulatorCursorManager.getCursorType(player);
|
||||||
inventory.setItem(48, new SWItem(cursorType.material, "§7Placing §8-§e " + cursorType.name, clickType -> {
|
inventory.setItem(48, new SWItem(cursorType.material, "§7Placing §8-§e " + cursorType.name, clickType -> {
|
||||||
new SimulatorCursorSwitcherGui(player, simulator, this).open();
|
new SimulatorCursorSwitcherGui(player, simulator, this).open();
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import de.steamwar.bausystem.features.tracer.rendering.TraceEntity;
|
|||||||
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
|
import de.steamwar.bausystem.features.tracer.rendering.ViewFlag;
|
||||||
import de.steamwar.bausystem.region.Region;
|
import de.steamwar.bausystem.region.Region;
|
||||||
import de.steamwar.entity.REntity;
|
import de.steamwar.entity.REntity;
|
||||||
|
import de.steamwar.entity.REntityAction;
|
||||||
import de.steamwar.entity.REntityServer;
|
import de.steamwar.entity.REntityServer;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -143,14 +144,6 @@ public class Trace {
|
|||||||
} else {
|
} else {
|
||||||
entityServer = new REntityServer();
|
entityServer = new REntityServer();
|
||||||
entityServer.addPlayer(player);
|
entityServer.addPlayer(player);
|
||||||
entityServer.setCallback((p, rEntity, entityAction) -> {
|
|
||||||
if (entityAction != REntityServer.EntityAction.INTERACT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rEntity instanceof TraceEntity) {
|
|
||||||
((TraceEntity) rEntity).printIntoChat(p);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
entityServerMap.put(player, entityServer);
|
entityServerMap.put(player, entityServer);
|
||||||
}
|
}
|
||||||
render(getRecords(), entityServer, playerTraceShowData);
|
render(getRecords(), entityServer, playerTraceShowData);
|
||||||
@@ -167,14 +160,6 @@ public class Trace {
|
|||||||
REntityServer entityServer = entityServerMap.computeIfAbsent(player, k -> {
|
REntityServer entityServer = entityServerMap.computeIfAbsent(player, k -> {
|
||||||
REntityServer newEntityServer = new REntityServer();
|
REntityServer newEntityServer = new REntityServer();
|
||||||
newEntityServer.addPlayer(k);
|
newEntityServer.addPlayer(k);
|
||||||
newEntityServer.setCallback((p, rEntity, entityAction) -> {
|
|
||||||
if (entityAction != REntityServer.EntityAction.INTERACT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rEntity instanceof TraceEntity) {
|
|
||||||
((TraceEntity) rEntity).printIntoChat(p);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return newEntityServer;
|
return newEntityServer;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+36
-4
@@ -24,13 +24,18 @@ import de.steamwar.bausystem.configplayer.Config;
|
|||||||
import de.steamwar.bausystem.features.tracer.TNTPoint;
|
import de.steamwar.bausystem.features.tracer.TNTPoint;
|
||||||
import de.steamwar.bausystem.features.tracer.Trace;
|
import de.steamwar.bausystem.features.tracer.Trace;
|
||||||
import de.steamwar.bausystem.features.tracer.TraceManager;
|
import de.steamwar.bausystem.features.tracer.TraceManager;
|
||||||
|
import de.steamwar.entity.RBlockDisplay;
|
||||||
|
import de.steamwar.entity.REntityAction;
|
||||||
import de.steamwar.entity.REntityServer;
|
import de.steamwar.entity.REntityServer;
|
||||||
import de.steamwar.entity.RFallingBlockEntity;
|
import de.steamwar.entity.RInteraction;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.md_5.bungee.api.chat.ClickEvent;
|
import net.md_5.bungee.api.chat.ClickEvent;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Transformation;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
import yapion.hierarchy.types.YAPIONValue;
|
import yapion.hierarchy.types.YAPIONValue;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -41,7 +46,16 @@ import static de.steamwar.bausystem.features.util.TNTClickListener.TNT_CLICK_DET
|
|||||||
/**
|
/**
|
||||||
* Wrapper for the rendering of a record bundle
|
* Wrapper for the rendering of a record bundle
|
||||||
*/
|
*/
|
||||||
public class TraceEntity extends RFallingBlockEntity {
|
public class TraceEntity extends RBlockDisplay {
|
||||||
|
|
||||||
|
private static final float TNT_VISUAL_SCALE = 0.98F;
|
||||||
|
private static final float TNT_VISUAL_OFFSET = -TNT_VISUAL_SCALE / 2.0F;
|
||||||
|
private static final Transformation TNT_VISUAL_TRANSFORM = new Transformation(
|
||||||
|
new Vector3f(TNT_VISUAL_OFFSET, 0.0F, TNT_VISUAL_OFFSET),
|
||||||
|
new Quaternionf(0, 0, 0, 1),
|
||||||
|
new Vector3f(TNT_VISUAL_SCALE, TNT_VISUAL_SCALE, TNT_VISUAL_SCALE),
|
||||||
|
new Quaternionf(0, 0, 0, 1)
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The records represented by this REntity
|
* The records represented by this REntity
|
||||||
@@ -55,13 +69,31 @@ public class TraceEntity extends RFallingBlockEntity {
|
|||||||
private final String uniqueTntIdsString;
|
private final String uniqueTntIdsString;
|
||||||
|
|
||||||
private final Trace trace;
|
private final Trace trace;
|
||||||
|
private final RInteraction hitbox;
|
||||||
|
|
||||||
public TraceEntity(REntityServer server, Location location, boolean isExplosion, List<TNTPoint> records, Trace trace) {
|
public TraceEntity(REntityServer server, Location location, boolean isExplosion, List<TNTPoint> records, Trace trace) {
|
||||||
super(server, location, isExplosion ? Material.RED_STAINED_GLASS : Material.TNT);
|
super(server, location);
|
||||||
|
Material material = isExplosion ? Material.RED_STAINED_GLASS : Material.TNT;
|
||||||
this.records = records;
|
this.records = records;
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
uniqueTntIdsString = records.stream().map(TNTPoint::getTntId).distinct().map(Object::toString).collect(Collectors.joining(" "));
|
uniqueTntIdsString = records.stream().map(TNTPoint::getTntId).distinct().map(Object::toString).collect(Collectors.joining(" "));
|
||||||
setNoGravity(true);
|
hitbox = new RInteraction(server, location);
|
||||||
|
hitbox.setInteractionHeight(TNT_VISUAL_SCALE);
|
||||||
|
hitbox.setInteractionWidth(TNT_VISUAL_SCALE);
|
||||||
|
hitbox.setCallback((player, action) -> {
|
||||||
|
if (action == REntityAction.INTERACT) {
|
||||||
|
printIntoChat(player);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTransform(TNT_VISUAL_TRANSFORM);
|
||||||
|
setBlock(material.createBlockData());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void die() {
|
||||||
|
hitbox.die();
|
||||||
|
super.die();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+5
-5
@@ -20,8 +20,8 @@
|
|||||||
package de.steamwar.bausystem.features.tracer.rendering;
|
package de.steamwar.bausystem.features.tracer.rendering;
|
||||||
|
|
||||||
import de.steamwar.bausystem.features.tracer.TNTPoint;
|
import de.steamwar.bausystem.features.tracer.TNTPoint;
|
||||||
|
import de.steamwar.entity.RBlockDisplay;
|
||||||
import de.steamwar.entity.REntityServer;
|
import de.steamwar.entity.REntityServer;
|
||||||
import de.steamwar.entity.RFallingBlockEntity;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
@@ -129,8 +129,8 @@ public abstract class ViewFlag {
|
|||||||
|
|
||||||
Location yLocation = previous.getLocation().clone().add(0, delta.getY(), 0);
|
Location yLocation = previous.getLocation().clone().add(0, delta.getY(), 0);
|
||||||
if (yLocation.distanceSquared(representative.getLocation()) >= 1.0 / 256.0 && yLocation.distanceSquared(previous.getLocation()) >= 1.0 / 256.0) {
|
if (yLocation.distanceSquared(representative.getLocation()) >= 1.0 / 256.0 && yLocation.distanceSquared(previous.getLocation()) >= 1.0 / 256.0) {
|
||||||
RFallingBlockEntity y = new RFallingBlockEntity(server, yLocation, Material.WHITE_STAINED_GLASS);
|
RBlockDisplay y = new RBlockDisplay(server, yLocation);
|
||||||
y.setNoGravity(true);
|
y.setBlock(Material.WHITE_STAINED_GLASS.createBlockData());
|
||||||
}
|
}
|
||||||
|
|
||||||
Location secoundLocation;
|
Location secoundLocation;
|
||||||
@@ -141,8 +141,8 @@ public abstract class ViewFlag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (secoundLocation.distanceSquared(representative.getLocation()) >= 1.0 / 256.0 && secoundLocation.distanceSquared(previous.getLocation()) >= 1.0 / 256.0) {
|
if (secoundLocation.distanceSquared(representative.getLocation()) >= 1.0 / 256.0 && secoundLocation.distanceSquared(previous.getLocation()) >= 1.0 / 256.0) {
|
||||||
RFallingBlockEntity second = new RFallingBlockEntity(server, secoundLocation, Material.WHITE_STAINED_GLASS);
|
RBlockDisplay second = new RBlockDisplay(server, secoundLocation);
|
||||||
second.setNoGravity(true);
|
second.setBlock(Material.WHITE_STAINED_GLASS.createBlockData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ public class ArrowStopper {
|
|||||||
private void run() {
|
private void run() {
|
||||||
Recording.iterateOverEntities(AbstractArrow.class::isInstance, entity -> {
|
Recording.iterateOverEntities(AbstractArrow.class::isInstance, entity -> {
|
||||||
Projectile arrow = (Projectile) entity;
|
Projectile arrow = (Projectile) entity;
|
||||||
|
if(!(arrow.getShooter() instanceof Player)) return;
|
||||||
if (invalidEntity(arrow)) return;
|
if (invalidEntity(arrow)) return;
|
||||||
|
|
||||||
Location prevLocation = arrow.getLocation().toVector().subtract(arrow.getVelocity()).toLocation(arrow.getWorld());
|
Location prevLocation = arrow.getLocation().toVector().subtract(arrow.getVelocity()).toLocation(arrow.getWorld());
|
||||||
|
|||||||
+46
-7
@@ -38,7 +38,11 @@ import net.minecraft.core.registries.BuiltInRegistries;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.level.material.Fluids;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.craftbukkit.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -46,10 +50,12 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class TechHiderWrapper extends StateDependent implements Listener {
|
public class TechHiderWrapper extends StateDependent implements Listener {
|
||||||
|
|
||||||
@@ -57,9 +63,21 @@ public class TechHiderWrapper extends StateDependent implements Listener {
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final ConcurrentHashMap<Player, Region> hiddenRegion = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<Player, Region> hiddenRegion = new ConcurrentHashMap<>();
|
||||||
|
private final HullHider hullHider;
|
||||||
|
|
||||||
public TechHiderWrapper(HullHider hullHider) {
|
public TechHiderWrapper(HullHider hullHider) {
|
||||||
super(ENABLED, FightState.All);
|
super(ENABLED, FightState.All);
|
||||||
|
|
||||||
|
this.hullHider = hullHider;
|
||||||
|
|
||||||
|
new StateDependentListener(ENABLED, FightState.All, this);
|
||||||
|
register();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enable() {
|
||||||
|
Set<BlockState> blockStatesToObfuscate = getBlockStatesToHideFromMaterials(Config.GameModeConfig.Techhider.HiddenBlocks);
|
||||||
|
|
||||||
Set<Block> blocksToObfuscate = Config.GameModeConfig.Techhider.HiddenBlocks.stream()
|
Set<Block> blocksToObfuscate = Config.GameModeConfig.Techhider.HiddenBlocks.stream()
|
||||||
.map(CraftMagicNumbers::getBlock)
|
.map(CraftMagicNumbers::getBlock)
|
||||||
.collect(Collectors.toUnmodifiableSet());
|
.collect(Collectors.toUnmodifiableSet());
|
||||||
@@ -94,6 +112,11 @@ public class TechHiderWrapper extends StateDependent implements Listener {
|
|||||||
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blocksToObfuscate.contains(block);
|
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blocksToObfuscate.contains(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlayerPrivilegedToAccessBlockState(Player p, int blockX, int blockY, int blockZ, BlockState blockState) {
|
||||||
|
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blockStatesToObfuscate.contains(blockState);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO will require entity tracking on the netty thread to prevent future race conditions
|
// TODO will require entity tracking on the netty thread to prevent future race conditions
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlayerPrivilegedToAccessEntity(Player p, int entityId) {
|
public boolean isPlayerPrivilegedToAccessEntity(Player p, int entityId) {
|
||||||
@@ -116,13 +139,6 @@ public class TechHiderWrapper extends StateDependent implements Listener {
|
|||||||
return p.getGameMode() != GameMode.SPECTATOR;
|
return p.getGameMode() != GameMode.SPECTATOR;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
new StateDependentListener(ENABLED, FightState.All, this);
|
|
||||||
register();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enable() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -175,4 +191,27 @@ public class TechHiderWrapper extends StateDependent implements Listener {
|
|||||||
|
|
||||||
return Fight.getOpposite(team).getExtendRegion();
|
return Fight.getOpposite(team).getExtendRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Stream<BlockState> getWaterloggedBlockStates() {
|
||||||
|
FluidState waterFluidState = Fluids.WATER.getSource(false);
|
||||||
|
|
||||||
|
return BuiltInRegistries.BLOCK.stream()
|
||||||
|
.map((block) -> block.getStateDefinition().getPossibleStates())
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter((blockState -> blockState.getFluidState() == waterFluidState));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<BlockState> getBlockStatesToHideFromMaterials(Set<Material> materials) {
|
||||||
|
Stream<BlockState> allStatesFromMaterials = materials.stream()
|
||||||
|
.map(CraftMagicNumbers::getBlock)
|
||||||
|
.map((block) -> block.getStateDefinition().getPossibleStates())
|
||||||
|
.flatMap(Collection::stream);
|
||||||
|
|
||||||
|
if(materials.contains(Material.WATER)) {
|
||||||
|
return Stream.concat(allStatesFromMaterials, getWaterloggedBlockStates()).collect(Collectors.toUnmodifiableSet());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return allStatesFromMaterials.collect(Collectors.toUnmodifiableSet());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,9 @@
|
|||||||
package de.steamwar.lobby.boatrace;
|
package de.steamwar.lobby.boatrace;
|
||||||
|
|
||||||
import de.steamwar.entity.REntity;
|
import de.steamwar.entity.REntity;
|
||||||
|
import de.steamwar.entity.REntityAction;
|
||||||
import de.steamwar.entity.REntityServer;
|
import de.steamwar.entity.REntityServer;
|
||||||
|
import de.steamwar.entity.RInteraction;
|
||||||
import de.steamwar.lobby.LobbySystem;
|
import de.steamwar.lobby.LobbySystem;
|
||||||
import de.steamwar.lobby.util.LeaderboardManager;
|
import de.steamwar.lobby.util.LeaderboardManager;
|
||||||
import de.steamwar.sql.SteamwarUser;
|
import de.steamwar.sql.SteamwarUser;
|
||||||
@@ -58,11 +60,12 @@ public class BoatRace implements EventListener, Listener {
|
|||||||
|
|
||||||
static {
|
static {
|
||||||
boatNpcServer = new REntityServer();
|
boatNpcServer = new REntityServer();
|
||||||
REntity starter = new REntity(boatNpcServer, EntityType.VILLAGER, BoatRacePositions.NPC);
|
new REntity(boatNpcServer, EntityType.VILLAGER, BoatRacePositions.NPC);
|
||||||
boatNpcServer.setCallback((player, rEntity, entityAction) -> {
|
RInteraction interaction = new RInteraction(boatNpcServer, BoatRacePositions.NPC.clone().subtract(0.5, 0, 0.5));
|
||||||
if (rEntity != starter) return;
|
interaction.setInteractionHeight(1.95f);
|
||||||
Bukkit.getWorlds().get(0).getEntities().stream().filter(entity -> entity.getType() == EntityType.END_CRYSTAL).forEach(Entity::remove);
|
interaction.setCallback((player, entity, action) -> {
|
||||||
if (entityAction == REntityServer.EntityAction.INTERACT && !oneNotStarted) {
|
Bukkit.getWorlds().get(0).getEntities().stream().filter(e -> e.getType() == EntityType.END_CRYSTAL).forEach(Entity::remove);
|
||||||
|
if (action == REntityAction.INTERACT && !oneNotStarted) {
|
||||||
oneNotStarted = true;
|
oneNotStarted = true;
|
||||||
new BoatRace(player);
|
new BoatRace(player);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,240 @@
|
|||||||
|
package de.steamwar.cursor;
|
||||||
|
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
|
import de.steamwar.entity.REntity;
|
||||||
|
import de.steamwar.entity.REntityServer;
|
||||||
|
import de.steamwar.entity.RFallingBlockEntity;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Cursor implements SWPlayer.Component {
|
||||||
|
private final World WORLD = Bukkit.getWorlds().get(0);
|
||||||
|
|
||||||
|
private final REntityServer targetServer;
|
||||||
|
private final Player owner;
|
||||||
|
|
||||||
|
private final AtomicBoolean isRendering = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
private RFallingBlockEntity cursorEntity;
|
||||||
|
private final REntityServer cursorServer;
|
||||||
|
private Location cursorLocation;
|
||||||
|
private REntity hitEntity;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private Material cursorMaterial;
|
||||||
|
@Setter
|
||||||
|
private List<CursorMode> allowedCursorModes;
|
||||||
|
private final Material highlightMaterial;
|
||||||
|
private final ClickHandler onClick;
|
||||||
|
private final BiConsumer<Location, Optional<REntity>> onRender;
|
||||||
|
|
||||||
|
|
||||||
|
public Cursor(REntityServer targetServer, Player owner, Material highlightMaterial, Material cursorMaterial, List<CursorMode> allowedModes, ClickHandler onClick) {
|
||||||
|
this(targetServer, owner, highlightMaterial, cursorMaterial, allowedModes, onClick, (location, hitEntity) -> {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor(REntityServer targetServer, Player owner, Material highlightMaterial, Material cursorMaterial, List<CursorMode> allowedModes, ClickHandler onClick, BiConsumer<Location, Optional<REntity>> onRender) {
|
||||||
|
this.targetServer = targetServer;
|
||||||
|
this.owner = owner;
|
||||||
|
this.highlightMaterial = highlightMaterial;
|
||||||
|
this.cursorMaterial = cursorMaterial;
|
||||||
|
this.allowedCursorModes = allowedModes;
|
||||||
|
this.onClick = onClick;
|
||||||
|
this.onRender = onRender;
|
||||||
|
|
||||||
|
cursorServer = new REntityServer();
|
||||||
|
cursorServer.addPlayer(owner);
|
||||||
|
|
||||||
|
SWPlayer.of(owner).setComponent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderDeduplicated() {
|
||||||
|
if (!isRendering.getAndSet(true)) {
|
||||||
|
render();
|
||||||
|
isRendering.set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void render() {
|
||||||
|
RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(owner, owner.getLocation(), targetServer.getEntities());
|
||||||
|
if (rayTraceResult == null) {
|
||||||
|
if (cursorEntity != null)
|
||||||
|
cursorEntity.die();
|
||||||
|
cursorEntity = null;
|
||||||
|
cursorLocation = null;
|
||||||
|
hitEntity = null;
|
||||||
|
onRender.accept(null, Optional.empty());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
REntity hitEntity = rayTraceResult.getHitEntity() == cursorEntity ? null : rayTraceResult.getHitEntity();
|
||||||
|
|
||||||
|
|
||||||
|
Material activeCursorMaterial = hitEntity == null ? cursorMaterial : highlightMaterial;
|
||||||
|
CursorMode activeCursorMode = allowedCursorModes.stream().filter((mode) -> mode.isActive.test(owner)).min(Comparator.comparingInt(a -> a.priority))
|
||||||
|
.orElse(CursorMode.BLOCK_ALIGNED);
|
||||||
|
|
||||||
|
Location activeCursorLocation = hitEntity == null ? activeCursorMode.positionTransform.apply(owner, rayTraceResult).toLocation(WORLD)
|
||||||
|
: new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ()).toLocation(WORLD);
|
||||||
|
|
||||||
|
cursorLocation = activeCursorLocation;
|
||||||
|
this.hitEntity = hitEntity;
|
||||||
|
|
||||||
|
if (cursorEntity == null) {
|
||||||
|
cursorEntity = new RFallingBlockEntity(cursorServer, activeCursorLocation, activeCursorMaterial);
|
||||||
|
cursorEntity.setNoGravity(true);
|
||||||
|
} else if (cursorEntity.getMaterial() == activeCursorMaterial) {
|
||||||
|
cursorEntity.move(activeCursorLocation);
|
||||||
|
} else {
|
||||||
|
cursorEntity.die();
|
||||||
|
cursorEntity = new RFallingBlockEntity(cursorServer, activeCursorLocation, activeCursorMaterial);
|
||||||
|
cursorEntity.setNoGravity(true);
|
||||||
|
if (activeCursorMaterial == highlightMaterial) {
|
||||||
|
cursorEntity.setGlowing(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onRender.accept(cursorLocation, Optional.ofNullable(hitEntity));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handlePlayerClick(Action clickAction) {
|
||||||
|
renderDeduplicated();
|
||||||
|
onClick.onClick(this.cursorLocation, Optional.ofNullable(this.hitEntity), clickAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnmount(SWPlayer player) {
|
||||||
|
cursorServer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum CursorMode {
|
||||||
|
FREE(1, (player, rayTraceResult) -> {
|
||||||
|
Vector pos = rayTraceResult.getHitPosition();
|
||||||
|
|
||||||
|
BlockFace face = rayTraceResult.getHitBlockFace();
|
||||||
|
if (face != null) {
|
||||||
|
switch (face) {
|
||||||
|
case DOWN:
|
||||||
|
pos.setY(pos.getY() - 0.98);
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
pos.setX(pos.getX() + 0.49);
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
pos.setX(pos.getX() - 0.49);
|
||||||
|
break;
|
||||||
|
case NORTH:
|
||||||
|
pos.setZ(pos.getZ() - 0.49);
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
pos.setZ(pos.getZ() + 0.49);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (face.getModY() == 0 && player.isSneaking()) {
|
||||||
|
pos.setY(pos.getY() - 0.49);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}, Player::isSneaking),
|
||||||
|
|
||||||
|
SURFACE_ALIGNED(2, (player, rayTraceResult) -> {
|
||||||
|
Vector hitPosition = rayTraceResult.getHitPosition().clone();
|
||||||
|
Vector pos = blockAlignedPosition(rayTraceResult);
|
||||||
|
BlockFace face = rayTraceResult.getHitBlockFace();
|
||||||
|
|
||||||
|
if (face != null && face != BlockFace.SELF) {
|
||||||
|
switch (face) {
|
||||||
|
case UP:
|
||||||
|
pos.setY(hitPosition.getY());
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
pos.setY(hitPosition.getY() + face.getModY());
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
case WEST:
|
||||||
|
pos.setX(hitPosition.getX() + face.getModX() * 0.5);
|
||||||
|
break;
|
||||||
|
case NORTH:
|
||||||
|
case SOUTH:
|
||||||
|
pos.setZ(hitPosition.getZ() + face.getModZ() * 0.5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}, (player) -> true),
|
||||||
|
|
||||||
|
BLOCK_ALIGNED(0, (player, rayTraceResult) -> blockAlignedPosition(rayTraceResult), (player) -> true);
|
||||||
|
|
||||||
|
|
||||||
|
private final int priority;
|
||||||
|
private final BiFunction<Player, RayTraceUtils.RRayTraceResult, Vector> positionTransform;
|
||||||
|
private final Predicate<Player> isActive;
|
||||||
|
|
||||||
|
private static Vector blockAlignedPosition(RayTraceUtils.RRayTraceResult rayTraceResult) {
|
||||||
|
Vector pos = rayTraceResult.getHitPosition();
|
||||||
|
|
||||||
|
BlockFace face = rayTraceResult.getHitBlockFace();
|
||||||
|
if (face != null) {
|
||||||
|
switch (face) {
|
||||||
|
case DOWN:
|
||||||
|
pos.setY(pos.getY() - 0.98);
|
||||||
|
break;
|
||||||
|
case EAST:
|
||||||
|
pos.setX(pos.getX() + 0.49);
|
||||||
|
break;
|
||||||
|
case WEST:
|
||||||
|
pos.setX(pos.getX() - 0.49);
|
||||||
|
break;
|
||||||
|
case NORTH:
|
||||||
|
pos.setZ(pos.getZ() - 0.49);
|
||||||
|
break;
|
||||||
|
case SOUTH:
|
||||||
|
pos.setZ(pos.getZ() + 0.49);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.setX(pos.getBlockX() + 0.5);
|
||||||
|
if (pos.getY() - pos.getBlockY() != 0 && face == BlockFace.UP) {
|
||||||
|
pos.setY(pos.getBlockY() + 1.0);
|
||||||
|
} else {
|
||||||
|
pos.setY(pos.getBlockY());
|
||||||
|
}
|
||||||
|
pos.setZ(pos.getBlockZ() + 0.5);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ClickHandler {
|
||||||
|
void onClick(Location location, Optional<REntity> hitEntity, Action action);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package de.steamwar.cursor;
|
||||||
|
|
||||||
|
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||||
|
import de.steamwar.core.Core;
|
||||||
|
import de.steamwar.core.SWPlayer;
|
||||||
|
import de.steamwar.linkage.Linked;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.minecraft.network.protocol.Packet;
|
||||||
|
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Linked
|
||||||
|
public class CursorListener implements Listener {
|
||||||
|
@Getter
|
||||||
|
private static CursorListener instance;
|
||||||
|
|
||||||
|
public CursorListener() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Pos.class, this::updateCursorFromPacket);
|
||||||
|
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Rot.class, this::updateCursorFromPacket);
|
||||||
|
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.PosRot.class, this::updateCursorFromPacket);
|
||||||
|
|
||||||
|
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
|
||||||
|
SWPlayer.allWithSingleComponent(Cursor.class)
|
||||||
|
.map(SWPlayer.SWPlayerWithComponent::getComponent)
|
||||||
|
.forEach(Cursor::renderDeduplicated);
|
||||||
|
}, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packet<?> updateCursorFromPacket(Player player, Packet<?> packet) {
|
||||||
|
SWPlayer swPlayer = SWPlayer.of(player);
|
||||||
|
Optional<Cursor> activeCursor = swPlayer.getComponent(Cursor.class);
|
||||||
|
|
||||||
|
activeCursor.ifPresent(Cursor::renderDeduplicated);
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
|
SWPlayer.of(event.getPlayer()).getComponent(Cursor.class).ifPresent(cursor -> {
|
||||||
|
event.setCancelled(true);
|
||||||
|
cursor.handlePlayerClick(event.getAction());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This file is a part of the SteamWar software.
|
* This file is a part of the SteamWar software.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.steamwar.bausystem.utils;
|
package de.steamwar.cursor;
|
||||||
|
|
||||||
import de.steamwar.entity.REntity;
|
import de.steamwar.entity.REntity;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
package de.steamwar.entity;
|
package de.steamwar.entity;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@@ -27,13 +28,16 @@ import org.bukkit.entity.EntityType;
|
|||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class RArmorStand extends REntity {
|
@Getter
|
||||||
|
public class RArmorStand extends REntity implements RInteractableEntity<RArmorStand> {
|
||||||
|
|
||||||
private static final EntityDataAccessor<Byte> sizeWatcher = new EntityDataAccessor<>(15, EntityDataSerializers.BYTE);
|
private static final EntityDataAccessor<Byte> sizeWatcher = new EntityDataAccessor<>(15, EntityDataSerializers.BYTE);
|
||||||
|
|
||||||
@Getter
|
|
||||||
private final Size size;
|
private final Size size;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private REntityActionListener<RArmorStand> callback = null;
|
||||||
|
|
||||||
public RArmorStand(REntityServer server, Location location, Size size) {
|
public RArmorStand(REntityServer server, Location location, Size size) {
|
||||||
super(server, EntityType.ARMOR_STAND, location, 0);
|
super(server, EntityType.ARMOR_STAND, location, 0);
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2026 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.entity;
|
||||||
|
|
||||||
|
public enum REntityAction {
|
||||||
|
INTERACT,
|
||||||
|
ATTACK,
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2026 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.entity;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public interface REntityActionListener<E extends REntity> {
|
||||||
|
void onAction(Player player, E entity, REntityAction action);
|
||||||
|
}
|
||||||
@@ -51,7 +51,6 @@ public class REntityServer implements Listener {
|
|||||||
private final HashMap<Player, Location> lastLocation = new HashMap<>();
|
private final HashMap<Player, Location> lastLocation = new HashMap<>();
|
||||||
private final HashMap<Player, Integer> viewDistance = new HashMap<>();
|
private final HashMap<Player, Integer> viewDistance = new HashMap<>();
|
||||||
|
|
||||||
private EntityActionListener callback = null;
|
|
||||||
private final Set<Player> playersThatClicked = Collections.synchronizedSet(new HashSet<>());
|
private final Set<Player> playersThatClicked = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
private final BiFunction<Player, ServerboundInteractPacket, Object> filter = (player, packet) -> {
|
private final BiFunction<Player, ServerboundInteractPacket, Object> filter = (player, packet) -> {
|
||||||
@@ -61,26 +60,20 @@ public class REntityServer implements Listener {
|
|||||||
if (playersThatClicked.contains(player)) return null;
|
if (playersThatClicked.contains(player)) return null;
|
||||||
|
|
||||||
playersThatClicked.add(player);
|
playersThatClicked.add(player);
|
||||||
EntityAction action = packet.isAttack() ? EntityAction.ATTACK : EntityAction.INTERACT;
|
REntityAction action = packet.isAttack() ? REntityAction.ATTACK : REntityAction.INTERACT;
|
||||||
Bukkit.getScheduler().runTask(Core.getInstance(), () -> {
|
Bukkit.getScheduler().runTask(Core.getInstance(), () -> {
|
||||||
playersThatClicked.remove(player);
|
playersThatClicked.remove(player);
|
||||||
callback.onAction(player, entity, action);
|
if (entity instanceof RInteractableEntity interactable && interactable.getCallback() != null) {
|
||||||
|
interactable.getCallback().onAction(player, entity, action);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
public REntityServer() {
|
public REntityServer() {
|
||||||
Core.getInstance().getServer().getPluginManager().registerEvents(this, Core.getInstance());
|
Core.getInstance().getServer().getPluginManager().registerEvents(this, Core.getInstance());
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallback(EntityActionListener callback) {
|
|
||||||
boolean uninitialized = this.callback == null;
|
|
||||||
this.callback = callback;
|
|
||||||
|
|
||||||
if (uninitialized) {
|
|
||||||
TinyProtocol.instance.addFilter(ServerboundInteractPacket.class, filter);
|
TinyProtocol.instance.addFilter(ServerboundInteractPacket.class, filter);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void addPlayer(Player player) {
|
public void addPlayer(Player player) {
|
||||||
Location location = player.getLocation();
|
Location location = player.getLocation();
|
||||||
@@ -293,13 +286,4 @@ public class REntityServer implements Listener {
|
|||||||
private long chunkToId(int x, int z) {
|
private long chunkToId(int x, int z) {
|
||||||
return ((long) x << 32) + z;
|
return ((long) x << 32) + z;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum EntityAction {
|
|
||||||
INTERACT,
|
|
||||||
ATTACK,
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface EntityActionListener {
|
|
||||||
void onAction(Player player, REntity entity, EntityAction action);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,16 +20,21 @@
|
|||||||
package de.steamwar.entity;
|
package de.steamwar.entity;
|
||||||
|
|
||||||
import de.steamwar.techhider.BlockIds;
|
import de.steamwar.techhider.BlockIds;
|
||||||
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class RFallingBlockEntity extends REntity {
|
public class RFallingBlockEntity extends REntity implements RInteractableEntity<RFallingBlockEntity> {
|
||||||
|
|
||||||
private final Material material;
|
private final Material material;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private REntityActionListener<RFallingBlockEntity> callback = null;
|
||||||
|
|
||||||
public RFallingBlockEntity(REntityServer server, Location location, Material material) {
|
public RFallingBlockEntity(REntityServer server, Location location, Material material) {
|
||||||
super(server, EntityType.FALLING_BLOCK, location, BlockIds.impl.materialToId(material));
|
super(server, EntityType.FALLING_BLOCK, location, BlockIds.impl.materialToId(material));
|
||||||
this.material = material;
|
this.material = material;
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2026 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.entity;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
public interface RInteractableEntity<E extends REntity> {
|
||||||
|
REntityActionListener<E> getCallback();
|
||||||
|
|
||||||
|
void setCallback(REntityActionListener<E> callback);
|
||||||
|
|
||||||
|
default void setCallback(BiConsumer<Player, REntityAction> callback) {
|
||||||
|
setCallback((player, interaction, entityAction) -> callback.accept(player, entityAction));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2026 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.entity;
|
||||||
|
|
||||||
|
import de.steamwar.core.BountifulWrapper;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* !! This class cannot be used in Versions lower than or equal to 1.19.4 !!
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class RInteraction extends REntity implements RInteractableEntity<RInteraction> {
|
||||||
|
|
||||||
|
protected final Consumer<Object> updatePacketSink = o -> server.updateEntity(this, o);
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private REntityActionListener<RInteraction> callback = null;
|
||||||
|
|
||||||
|
private float interactionWidth = 1.0f;
|
||||||
|
private float interactionHeight = 1.0f;
|
||||||
|
private boolean responsive = false;
|
||||||
|
|
||||||
|
public RInteraction(REntityServer server, Location location) {
|
||||||
|
super(server, EntityType.INTERACTION, location);
|
||||||
|
server.addEntity(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void postSpawn(Consumer<Object> packetSink) {
|
||||||
|
super.postSpawn(packetSink);
|
||||||
|
sendPacket(packetSink,
|
||||||
|
this::getInteractionWidthData,
|
||||||
|
this::getInteractionHeightData,
|
||||||
|
this::getResponsiveData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
protected final void sendPacket(Consumer<Object> packetSink, BiConsumer<Boolean, BiConsumer<Object, Object>>... dataSinkSinks) {
|
||||||
|
List<Object> keyValueData = new ArrayList<>();
|
||||||
|
boolean ignoreDefault = packetSink == updatePacketSink;
|
||||||
|
for (BiConsumer<Boolean, BiConsumer<Object, Object>> dataSinkSink : dataSinkSinks) {
|
||||||
|
dataSinkSink.accept(ignoreDefault, (dataWatcher, value) -> {
|
||||||
|
keyValueData.add(dataWatcher);
|
||||||
|
keyValueData.add(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!keyValueData.isEmpty()) {
|
||||||
|
packetSink.accept(getDataWatcherPacket(keyValueData.toArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInteractionWidth(float interactionWidth) {
|
||||||
|
this.interactionWidth = interactionWidth;
|
||||||
|
sendPacket(updatePacketSink, this::getInteractionWidthData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Object interactionWidthWatcher = BountifulWrapper.impl.getDataWatcherObject(8, Float.class);
|
||||||
|
|
||||||
|
private void getInteractionWidthData(boolean ignoreDefault, BiConsumer<Object, Object> dataSink) {
|
||||||
|
if (ignoreDefault || interactionWidth != 1.0) {
|
||||||
|
dataSink.accept(interactionWidthWatcher, interactionWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInteractionHeight(float interactionHeight) {
|
||||||
|
this.interactionHeight = interactionHeight;
|
||||||
|
sendPacket(updatePacketSink, this::getInteractionHeightData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Object interactionHeightWatcher = BountifulWrapper.impl.getDataWatcherObject(9, Float.class);
|
||||||
|
|
||||||
|
private void getInteractionHeightData(boolean ignoreDefault, BiConsumer<Object, Object> dataSink) {
|
||||||
|
if (ignoreDefault || interactionHeight != 1.0) {
|
||||||
|
dataSink.accept(interactionHeightWatcher, interactionHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponsive(boolean responsive) {
|
||||||
|
this.responsive = responsive;
|
||||||
|
sendPacket(updatePacketSink, this::getResponsiveData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Object responsiveWatcher = BountifulWrapper.impl.getDataWatcherObject(10, Boolean.class);
|
||||||
|
|
||||||
|
private void getResponsiveData(boolean ignoreDefault, BiConsumer<Object, Object> dataSink) {
|
||||||
|
if (ignoreDefault || !responsive) {
|
||||||
|
dataSink.accept(responsiveWatcher, responsive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import de.steamwar.network.CoreNetworkHandler;
|
|||||||
import de.steamwar.network.NetworkSender;
|
import de.steamwar.network.NetworkSender;
|
||||||
import de.steamwar.network.packets.common.PlayerSkinRequestPacket;
|
import de.steamwar.network.packets.common.PlayerSkinRequestPacket;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
|
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
@@ -39,7 +40,7 @@ import java.util.Map;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class RPlayer extends REntity {
|
public class RPlayer extends REntity implements RInteractableEntity<RPlayer> {
|
||||||
|
|
||||||
private static final Object skinPartsDataWatcher = BountifulWrapper.impl.getDataWatcherObject(17, Byte.class);
|
private static final Object skinPartsDataWatcher = BountifulWrapper.impl.getDataWatcherObject(17, Byte.class);
|
||||||
|
|
||||||
@@ -48,6 +49,10 @@ public class RPlayer extends REntity {
|
|||||||
@Getter
|
@Getter
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
private REntityActionListener<RPlayer> callback = null;
|
||||||
|
|
||||||
public RPlayer(REntityServer server, UUID uuid, String name, Location location) {
|
public RPlayer(REntityServer server, UUID uuid, String name, Location location) {
|
||||||
super(server, EntityType.PLAYER, UUID.nameUUIDFromBytes(uuid.toString().getBytes(StandardCharsets.UTF_8)), location, 0);
|
super(server, EntityType.PLAYER, UUID.nameUUIDFromBytes(uuid.toString().getBytes(StandardCharsets.UTF_8)), location, 0);
|
||||||
this.actualUUID = uuid;
|
this.actualUUID = uuid;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ package de.steamwar.techhider;
|
|||||||
|
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public interface AccessPrivilegeProvider {
|
public interface AccessPrivilegeProvider {
|
||||||
@@ -30,6 +31,8 @@ public interface AccessPrivilegeProvider {
|
|||||||
|
|
||||||
boolean isPlayerPrivilegedToAccessBlock(Player p, int blockX, int blockY, int blockZ, Block block);
|
boolean isPlayerPrivilegedToAccessBlock(Player p, int blockX, int blockY, int blockZ, Block block);
|
||||||
|
|
||||||
|
boolean isPlayerPrivilegedToAccessBlockState(Player p, int blockX, int blockY, int blockZ, BlockState blockState);
|
||||||
|
|
||||||
boolean isPlayerPrivilegedToAccessEntity(Player p, int entityId);
|
boolean isPlayerPrivilegedToAccessEntity(Player p, int entityId);
|
||||||
|
|
||||||
boolean isPlayerPrivilegedToAccessBlockEntity(Player p, int blockX, int blockY, int blockZ, BlockEntityType<?> type);
|
boolean isPlayerPrivilegedToAccessBlockEntity(Player p, int blockX, int blockY, int blockZ, BlockEntityType<?> type);
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ public class ChunkHider {
|
|||||||
out.readBytes(data);
|
out.readBytes(data);
|
||||||
|
|
||||||
List<Object> blockEntities = chunkBlockEntitiesDataField.get(chunkData);
|
List<Object> blockEntities = chunkBlockEntitiesDataField.get(chunkData);
|
||||||
List<Object> filteredBlockEntities = filterBlockEntities(player, blockEntities);
|
List<Object> filteredBlockEntities = filterBlockEntities(player, blockEntities, chunkX, chunkZ);
|
||||||
|
|
||||||
return buildNewChunkPacket(packet, data, filteredBlockEntities);
|
return buildNewChunkPacket(packet, data, filteredBlockEntities);
|
||||||
|
|
||||||
@@ -201,7 +201,7 @@ public class ChunkHider {
|
|||||||
Block block = blockState.getBlock();
|
Block block = blockState.getBlock();
|
||||||
|
|
||||||
|
|
||||||
if (accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, worldX, worldY, worldZ) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlock(player, worldX, worldY, worldZ, block)) {
|
if (accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, worldX, worldY, worldZ) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlock(player, worldX, worldY, worldZ, block) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlockState(player, worldX, worldY, worldZ, blockState)) {
|
||||||
obfuscatedData[blockDataIndex] = blockId;
|
obfuscatedData[blockDataIndex] = blockId;
|
||||||
} else {
|
} else {
|
||||||
obfuscatedData[blockDataIndex] = blockIdUsedForHiding;
|
obfuscatedData[blockDataIndex] = blockIdUsedForHiding;
|
||||||
@@ -256,18 +256,24 @@ public class ChunkHider {
|
|||||||
private static final Reflection.Field<Integer> packedXZField = Reflection.getField(blockEntitiyInfoClass, int.class, 0);
|
private static final Reflection.Field<Integer> packedXZField = Reflection.getField(blockEntitiyInfoClass, int.class, 0);
|
||||||
private static final Reflection.Field<Integer> yField = Reflection.getField(blockEntitiyInfoClass, int.class, 1);
|
private static final Reflection.Field<Integer> yField = Reflection.getField(blockEntitiyInfoClass, int.class, 1);
|
||||||
|
|
||||||
private List<Object> filterBlockEntities(Player player, List<Object> blockEntities) {
|
private List<Object> filterBlockEntities(Player player, List<Object> blockEntities, int chunkX, int chunkZ) {
|
||||||
|
int fourBitBitmask = 0b0000_1111;
|
||||||
|
|
||||||
return blockEntities.stream()
|
return blockEntities.stream()
|
||||||
.filter((blockEntityInfo) -> {
|
.filter((blockEntityInfo) -> {
|
||||||
BlockEntityType<?> type = blockEntityInfoTypeField.get(blockEntityInfo);
|
BlockEntityType<?> type = blockEntityInfoTypeField.get(blockEntityInfo);
|
||||||
|
|
||||||
int packedXZ = packedXZField.get(blockEntityInfo);
|
int packedXZ = packedXZField.get(blockEntityInfo);
|
||||||
|
|
||||||
int y = yField.get(blockEntityInfo);
|
int localX = (packedXZ >> 4) & fourBitBitmask;
|
||||||
int x = SectionPos.sectionRelativeX((short) packedXZ);
|
int localZ = packedXZ & fourBitBitmask;
|
||||||
int z = SectionPos.sectionRelativeZ((short) packedXZ);
|
|
||||||
|
|
||||||
return accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, x, y, z) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlockEntity(player, x, y, z, type);
|
int worldX = (chunkX * SECTION_SPAN_SIZE) + localX;
|
||||||
|
int worldZ = (chunkZ * SECTION_SPAN_SIZE) + localZ;
|
||||||
|
|
||||||
|
int worldY = yField.get(blockEntityInfo);
|
||||||
|
|
||||||
|
return accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, worldX, worldY, worldZ) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlockEntity(player, worldX, worldY, worldZ, type);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ public class TechHider {
|
|||||||
ClientboundSetHeldSlotPacket.class, // 7.1.104 Set Held Item (Player owning the channel)
|
ClientboundSetHeldSlotPacket.class, // 7.1.104 Set Held Item (Player owning the channel)
|
||||||
ClientboundSetObjectivePacket.class, // 7.1.105 Update Objectives
|
ClientboundSetObjectivePacket.class, // 7.1.105 Update Objectives
|
||||||
ClientboundSetPlayerInventoryPacket.class, // 7.1.107 Set Player Inventory Slot (Player owning the channel)
|
ClientboundSetPlayerInventoryPacket.class, // 7.1.107 Set Player Inventory Slot (Player owning the channel)
|
||||||
ClientboundSetPlayerTeamPacket.class, // 7.1.108 Update Teams
|
// ClientboundSetPlayerTeamPacket.class, // 7.1.108 Update Teams
|
||||||
ClientboundSetScorePacket.class, // 7.1.109 Update Score
|
ClientboundSetScorePacket.class, // 7.1.109 Update Score
|
||||||
ClientboundSetSimulationDistancePacket.class, // 7.1.110 Set Simulation Distance
|
ClientboundSetSimulationDistancePacket.class, // 7.1.110 Set Simulation Distance
|
||||||
ClientboundSetSubtitleTextPacket.class, // 7.1.111 Set Subtitle Text
|
ClientboundSetSubtitleTextPacket.class, // 7.1.111 Set Subtitle Text
|
||||||
@@ -423,12 +423,13 @@ public class TechHider {
|
|||||||
|
|
||||||
private Packet<?> processBlockUpdatePacket(Player player, ClientboundBlockUpdatePacket packet) {
|
private Packet<?> processBlockUpdatePacket(Player player, ClientboundBlockUpdatePacket packet) {
|
||||||
BlockPos blockPos = packet.getPos();
|
BlockPos blockPos = packet.getPos();
|
||||||
Block block = packet.getBlockState().getBlock();
|
BlockState blockState = packet.getBlockState();
|
||||||
|
Block block = blockState.getBlock();
|
||||||
int blockX = blockPos.getX();
|
int blockX = blockPos.getX();
|
||||||
int blockY = blockPos.getY();
|
int blockY = blockPos.getY();
|
||||||
int blockZ = blockPos.getZ();
|
int blockZ = blockPos.getZ();
|
||||||
|
|
||||||
if (privilegeProvider.isPlayerPrivilegedToAccessPosition(player, blockX, blockY, blockZ) && privilegeProvider.isPlayerPrivilegedToAccessBlock(player, blockX, blockY, blockZ, block)) {
|
if (privilegeProvider.isPlayerPrivilegedToAccessPosition(player, blockX, blockY, blockZ) && privilegeProvider.isPlayerPrivilegedToAccessBlock(player, blockX, blockY, blockZ, block) && privilegeProvider.isPlayerPrivilegedToAccessBlockState(player, blockX, blockY, blockZ, blockState)) {
|
||||||
return packet;
|
return packet;
|
||||||
} else if (privilegeProvider.isPlayerPrivilegedToAccessPosition(player, blockX, blockY, blockZ)) {
|
} else if (privilegeProvider.isPlayerPrivilegedToAccessPosition(player, blockX, blockY, blockZ)) {
|
||||||
return new ClientboundBlockUpdatePacket(blockPos, blockStateUsedForObfuscation);
|
return new ClientboundBlockUpdatePacket(blockPos, blockStateUsedForObfuscation);
|
||||||
@@ -471,7 +472,6 @@ public class TechHider {
|
|||||||
short[] oldPos = oldPosField.get(packet);
|
short[] oldPos = oldPosField.get(packet);
|
||||||
BlockState[] oldStates = oldStatesField.get(packet);
|
BlockState[] oldStates = oldStatesField.get(packet);
|
||||||
|
|
||||||
boolean modified = false;
|
|
||||||
List<Short> filteredPos = new ArrayList<>(oldPos.length);
|
List<Short> filteredPos = new ArrayList<>(oldPos.length);
|
||||||
List<BlockState> filteredStates = new ArrayList<>(oldStates.length);
|
List<BlockState> filteredStates = new ArrayList<>(oldStates.length);
|
||||||
|
|
||||||
@@ -484,12 +484,10 @@ public class TechHider {
|
|||||||
int worldY = sectionPos.relativeToBlockY(posShort);
|
int worldY = sectionPos.relativeToBlockY(posShort);
|
||||||
int worldZ = sectionPos.relativeToBlockZ(posShort);
|
int worldZ = sectionPos.relativeToBlockZ(posShort);
|
||||||
|
|
||||||
if (privilegeProvider.isPlayerPrivilegedToAccessPosition(p, worldX, worldY, worldZ) && privilegeProvider.isPlayerPrivilegedToAccessBlock(p, worldX, worldY, worldZ, block)) {
|
if (privilegeProvider.isPlayerPrivilegedToAccessPosition(p, worldX, worldY, worldZ) && privilegeProvider.isPlayerPrivilegedToAccessBlock(p, worldX, worldY, worldZ, block) && privilegeProvider.isPlayerPrivilegedToAccessBlockState(p, worldX, worldY, worldZ, state)) {
|
||||||
// TODO statefull !!!
|
|
||||||
filteredPos.add(posShort);
|
filteredPos.add(posShort);
|
||||||
filteredStates.add(state);
|
filteredStates.add(state);
|
||||||
} else if (privilegeProvider.isPlayerPrivilegedToAccessPosition(p, worldX, worldY, worldZ)) {
|
} else if (privilegeProvider.isPlayerPrivilegedToAccessPosition(p, worldX, worldY, worldZ)) {
|
||||||
modified = true;
|
|
||||||
filteredPos.add(posShort);
|
filteredPos.add(posShort);
|
||||||
filteredStates.add(blockStateUsedForObfuscation);
|
filteredStates.add(blockStateUsedForObfuscation);
|
||||||
}
|
}
|
||||||
@@ -498,9 +496,6 @@ public class TechHider {
|
|||||||
if (filteredStates.isEmpty()) {
|
if (filteredStates.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!modified) {
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
short[] newPos = new short[filteredPos.size()];
|
short[] newPos = new short[filteredPos.size()];
|
||||||
for (int i = 0; i < newPos.length; i++) {
|
for (int i = 0; i < newPos.length; i++) {
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ import net.md_5.bungee.api.chat.ClickEvent
|
|||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
object InviteCommand : SWCommand("invite") {
|
object InviteCommand : SWCommand("invite") {
|
||||||
|
init {
|
||||||
|
message = de.steamwar.tntleague.message
|
||||||
|
}
|
||||||
|
|
||||||
@Register
|
@Register
|
||||||
fun invitePlayer(@Validator("isLeader") sender: Player, target: Player) {
|
fun invitePlayer(@Validator("isLeader") sender: Player, target: Player) {
|
||||||
|
|||||||
@@ -42,11 +42,12 @@ dependencies {
|
|||||||
implementation(project(":CommandFramework"))
|
implementation(project(":CommandFramework"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<DevServer>("DevVelocity") {
|
tasks.register<VelocityServer>("DevVelocity") {
|
||||||
group = "run"
|
group = "run"
|
||||||
description = "Run a Dev Velocity"
|
description = "Run a Dev Velocity"
|
||||||
dependsOn(":VelocityCore:shadowJar")
|
dependsOn(":VelocityCore:shadowJar")
|
||||||
dependsOn(":VelocityCore:Persistent:jar")
|
dependsOn(":VelocityCore:Persistent:jar")
|
||||||
dependsOn(":VelocityCore:Dependencies:shadowJar")
|
dependsOn(":VelocityCore:Dependencies:shadowJar")
|
||||||
template = "DevVelocity"
|
template = "DevVelocity"
|
||||||
|
packetDecodeLogging=true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class ServerStarter {
|
|||||||
public ServerStarter event(EventFight eventFight) {
|
public ServerStarter event(EventFight eventFight) {
|
||||||
arena(ArenaMode.getByInternal(eventFight.getSpielmodus()), eventFight.getMap());
|
arena(ArenaMode.getByInternal(eventFight.getSpielmodus()), eventFight.getMap());
|
||||||
node = VelocityCore.local;
|
node = VelocityCore.local;
|
||||||
worldDir = EVENT_PATH;
|
worldDir = EVENT_PATH + "/" + serverToWorldName(Event.byId(eventFight.getEventID()).getEventName()) + "/" + eventFight.getStartTime().toLocalDateTime().format(DateTimeFormatter.ISO_LOCAL_DATE);
|
||||||
worldCleanup = () -> {
|
worldCleanup = () -> {
|
||||||
};
|
};
|
||||||
arguments.put("fightID", String.valueOf(eventFight.getFightID()));
|
arguments.put("fightID", String.valueOf(eventFight.getFightID()));
|
||||||
@@ -351,7 +351,7 @@ public class ServerStarter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String serverToWorldName(String serverName) {
|
public static String serverToWorldName(String serverName) {
|
||||||
return serverName.replace(' ', '_').replace("[", "").replace("]", "");
|
return serverName.replace(' ', '_').replace("[", "").replace("]", "").replace(".", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void copyWorld(Node node, String template, String target) {
|
public static void copyWorld(Node node, String template, String target) {
|
||||||
|
|||||||
@@ -307,6 +307,13 @@ public class CheckCommand extends SWCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove any added players from the schematic in the folder
|
||||||
|
for (SchematicNode schematicNode : SchematicNode.getSchematicNodeInNode(teamFolder.getNodeId())) {
|
||||||
|
for (NodeMember nodeMember : NodeMember.getNodeMembers(schematicNode.getNodeId())) {
|
||||||
|
nodeMember.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Copy Schem into team folder of -1 user
|
// Copy Schem into team folder of -1 user
|
||||||
String name = DateTimeFormatter.ofPattern("yyyy.MM.dd_HH:mm:ss").format(schematic.getLastUpdate().toLocalDateTime());
|
String name = DateTimeFormatter.ofPattern("yyyy.MM.dd_HH:mm:ss").format(schematic.getLastUpdate().toLocalDateTime());
|
||||||
NodeData data = NodeData.getLatest(schematic);
|
NodeData data = NodeData.getLatest(schematic);
|
||||||
@@ -316,14 +323,8 @@ public class CheckCommand extends SWCommand {
|
|||||||
// Accept the team folder schematic and set other to Normal as well as adding the original owner on the schematic
|
// Accept the team folder schematic and set other to Normal as well as adding the original owner on the schematic
|
||||||
node.setSchemtype(GameModeConfig.getBySchematicType(schematic.getSchemtype()).Schematic.Type);
|
node.setSchemtype(GameModeConfig.getBySchematicType(schematic.getSchemtype()).Schematic.Type);
|
||||||
NodeMember.createNodeMember(node.getNodeId(), schematic.getOwner());
|
NodeMember.createNodeMember(node.getNodeId(), schematic.getOwner());
|
||||||
|
for (NodeMember nodeMember : NodeMember.getNodeMembers(schematic.getId())) {
|
||||||
// Remove any added players from the schematic in the folder
|
|
||||||
for (SchematicNode schematicNode : SchematicNode.getSchematicNodeInNode(teamFolder.getNodeId())) {
|
|
||||||
if (schematicNode.getNodeId() == node.getNodeId()) continue;
|
|
||||||
for (NodeMember nodeMember : NodeMember.getNodeMembers(schematicNode.getNodeId())) {
|
|
||||||
NodeMember.createNodeMember(node.getNodeId(), nodeMember.getMember());
|
NodeMember.createNodeMember(node.getNodeId(), nodeMember.getMember());
|
||||||
nodeMember.delete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conclude by setting send in schematic to normal and broadcast
|
// Conclude by setting send in schematic to normal and broadcast
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ public class ReplayCommand extends SWCommand {
|
|||||||
super("replay");
|
super("replay");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Register
|
||||||
|
public void genericCommand(PlayerChatter sender) {
|
||||||
|
sender.system("REPLAY_UNAVAILABLE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
@Register
|
@Register
|
||||||
public void genericCommand(PlayerChatter sender, int replayId, @StaticValue(value = {"", "-a"}, allowISE = true) @OptionalValue("") boolean isAdmin, @OptionalValue("") String optionalMap) {
|
public void genericCommand(PlayerChatter sender, int replayId, @StaticValue(value = {"", "-a"}, allowISE = true) @OptionalValue("") boolean isAdmin, @OptionalValue("") String optionalMap) {
|
||||||
Fight fight = Fight.getById(replayId);
|
Fight fight = Fight.getById(replayId);
|
||||||
@@ -109,4 +116,5 @@ public class ReplayCommand extends SWCommand {
|
|||||||
private Message parseLeader(SteamwarUser leader, int players, boolean winner) {
|
private Message parseLeader(SteamwarUser leader, int players, boolean winner) {
|
||||||
return new Message("REPLAY_" + (players > 1 ? "" : "SOLO_") + (winner ? "WINNER" : "LOSER"), leader.getUserName(), players - 1);
|
return new Message("REPLAY_" + (players > 1 ? "" : "SOLO_") + (winner ? "WINNER" : "LOSER"), leader.getUserName(), players - 1);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -278,6 +278,19 @@ class DevServer extends DefaultTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VelocityServer extends DevServer {
|
||||||
|
@Input
|
||||||
|
@Optional
|
||||||
|
Boolean packetDecodeLogging = false
|
||||||
|
|
||||||
|
VelocityServer() {
|
||||||
|
super()
|
||||||
|
doFirst {
|
||||||
|
if(packetDecodeLogging) dParams.put("velocity.packet-decode-logging", "true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FightServer extends DevServer {
|
class FightServer extends DevServer {
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
|
|||||||
Reference in New Issue
Block a user