diff --git a/src/de/steamwar/spectatesystem/ConnectionAcceptor.java b/src/de/steamwar/spectatesystem/ConnectionAcceptor.java index 97d00c2..66e62c0 100644 --- a/src/de/steamwar/spectatesystem/ConnectionAcceptor.java +++ b/src/de/steamwar/spectatesystem/ConnectionAcceptor.java @@ -48,7 +48,7 @@ public class ConnectionAcceptor { new FightserverConnection(socket.accept()); } } catch (IOException e) { - Bukkit.getLogger().log(Level.WARNING, "Stopping accepting connections", e); + Bukkit.getLogger().log(Level.INFO, "Stopping accepting connections", e); } } } diff --git a/src/de/steamwar/spectatesystem/PacketProcessor.java b/src/de/steamwar/spectatesystem/PacketProcessor.java index 737bb7a..f2a53ec 100644 --- a/src/de/steamwar/spectatesystem/PacketProcessor.java +++ b/src/de/steamwar/spectatesystem/PacketProcessor.java @@ -20,6 +20,7 @@ package de.steamwar.spectatesystem; import com.sk89q.worldedit.EditSession; +import de.steamwar.spectatesystem.commands.InspectCommand; import de.steamwar.spectatesystem.elements.*; import de.steamwar.spectatesystem.util.BlockTextCreator; import de.steamwar.spectatesystem.util.ColorConverter; @@ -43,6 +44,7 @@ import org.bukkit.scheduler.BukkitTask; import java.io.EOFException; import java.io.IOException; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; import java.util.Objects; import java.util.logging.Level; @@ -54,26 +56,53 @@ class PacketProcessor { private final PacketSource source; private final BukkitTask task; + private final LinkedList syncList = new LinkedList<>(); + public PacketProcessor(PacketSource source){ this.source = source; - if(source.async()) - task = Bukkit.getScheduler().runTaskAsynchronously(SpectateSystem.get(), this::process); - else + if(source.async()) { + Bukkit.getScheduler().runTaskAsynchronously(SpectateSystem.get(), this::process); + task = Bukkit.getScheduler().runTaskTimer(SpectateSystem.get(), this::runSync, 1, 1); + }else task = Bukkit.getScheduler().runTaskTimer(SpectateSystem.get(), this::process, 1, 1); } - private void playerJoins() throws IOException{ + private void runSync() { + synchronized (syncList) { + for(Runnable runnable : syncList) { + try{ + runnable.run(); + }catch (Exception e) { + Bukkit.getLogger().log(Level.WARNING, "Failed to execute packet", e); + } + } + syncList.clear(); + } + } + + private void execSync(Runnable runnable){ + if (!source.async()) { + runnable.run(); + return; + } + + synchronized (syncList) { + syncList.add(runnable); + } + } + + private void playerJoins() throws IOException { int entityId = source.rInt(); int userId = source.rInt(); SteamwarUser user = SteamwarUser.get(userId); if(user == null) throw new IOException("Unknown user " + userId); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> new RPlayer(user.getUUID(), user.getUserName(), entityId)); + execSync(() -> new RPlayer(user.getUUID(), user.getUserName(), entityId)); } - private void entityMoves() throws IOException{ + private void entityMoves() throws IOException { int entityId = source.rInt(); double locX = source.rDouble(); double locY = source.rDouble(); @@ -82,33 +111,33 @@ class PacketProcessor { float yaw = source.rFloat(); byte headYaw = source.rByte(); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> REntity.getEntity(entityId).move(locX, locY, locZ, yaw, pitch, headYaw)); + execSync(() -> REntity.getEntity(entityId).move(locX, locY, locZ, yaw, pitch, headYaw)); } - private void entityDespawns() throws IOException{ + private void entityDespawns() throws IOException { int entityId = source.rInt(); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> REntity.getEntity(entityId).remove()); + execSync(() -> REntity.getEntity(entityId).remove()); } private void entitySneak() throws IOException { int entityId = source.rInt(); boolean sneaking = source.rBoolean(); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> REntity.getEntity(entityId).sneak(sneaking)); + execSync(() -> REntity.getEntity(entityId).sneak(sneaking)); } private void entityAnimation() throws IOException { int entityId = source.rInt(); byte animation = source.rByte(); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> REntity.getEntity(entityId).animation(animation)); + execSync(() -> REntity.getEntity(entityId).animation(animation)); } private void tntSpawn() throws IOException { int entityId = source.rInt(); - new RTnT(entityId); + execSync(() -> new RTnT(entityId)); } private void entityVelocity() throws IOException { @@ -118,7 +147,7 @@ class PacketProcessor { double dY = source.rDouble(); double dZ = source.rDouble(); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> { + execSync(() -> { REntity entity = REntity.getEntity(entityId); if(entity != null) entity.setMotion(dX, dY, dZ); @@ -131,19 +160,19 @@ class PacketProcessor { boolean enchanted = source.rBoolean(); String slot = source.rString(); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> ((RPlayer)REntity.getEntity(entityId)).setItem(item, enchanted, slot)); + execSync(() -> ((RPlayer)REntity.getEntity(entityId)).setItem(item, enchanted, slot)); } private void arrowSpawn() throws IOException { int entityId = source.rInt(); - new RArrow(entityId); + execSync(() -> new RArrow(entityId)); } private void fireballSpawn() throws IOException { int entityId = source.rInt(); - new RFireball(entityId); + execSync(() -> new RFireball(entityId)); } private void send(ChatMessageType type) throws IOException { @@ -171,6 +200,23 @@ class PacketProcessor { setBlock(x, y, z, blockState); } + private void setBlock(int x, int y, int z, int blockState){ + if(Config.ArenaMinX > x || Config.ArenaMaxX < x || Config.ArenaMinZ > z || Config.ArenaMaxZ < z) + return; //Outside of the arena + + if (!InspectCommand.inspecting && Config.TechhiderActive && Config.HiddenBlocks.contains(blockState)) { + blockState = Config.ObfuscateWith; + } + IBlockData blockData = Objects.requireNonNull(Block.REGISTRY_ID.fromId(blockState)); + execSync(() -> { + WorldServer cworld = ((CraftWorld)world).getHandle(); + BlockPosition pos = new BlockPosition(x, y, z); + cworld.removeTileEntity(pos); + cworld.setTypeAndData(pos, blockData, 1042); + cworld.getChunkProvider().flagDirty(pos); + }); + } + private void particle() throws IOException { double x = source.rDouble(); double y = source.rDouble(); @@ -178,7 +224,7 @@ class PacketProcessor { String particleName = source.rString(); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> world.spawnParticle(Particle.valueOf(particleName), x, y, z, 1)); + execSync(() -> world.spawnParticle(Particle.valueOf(particleName), x, y, z, 1)); } private void sound() throws IOException { @@ -195,7 +241,7 @@ class PacketProcessor { Sound sound = Sound.valueOf(soundName); SoundCategory sCategory = SoundCategory.valueOf(soundCategory); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> world.playSound(new Location(world, x, y, z), sound, sCategory, volume, pitch)); + execSync(() -> world.playSound(new Location(world, x, y, z), sound, sCategory, volume, pitch)); } private void soundAtPlayer() throws IOException { @@ -206,21 +252,21 @@ class PacketProcessor { Sound sound = Sound.valueOf(soundName); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> { + execSync(() -> { for(Player player : Bukkit.getOnlinePlayers()){ player.playSound(player.getLocation(), sound, volume, pitch); } }); } - private void pasteSchem(int cornerX, int cornerY, int cornerZ, boolean rotate, String prefix) throws IOException { + private void pasteSchem(int pasteX, int cornerY, int pasteZ, int cornerX, int cornerZ, boolean rotate, String prefix) throws IOException { int schemId = source.rInt(); Schematic schem = Schematic.getSchemFromDB(schemId); DyeColor c = ColorConverter.chat2dye(ChatColor.getByChar(ChatColor.getLastColors(prefix).replace("§", ""))); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> { + execSync(() -> { try { - EditSession e = Paster.pasteSchematic(schem, cornerX, cornerY, cornerZ, rotate); + EditSession e = Paster.pasteSchematic(schem, pasteX, cornerY, pasteZ, rotate); Paster.replaceTeamColor(e, c, cornerX, cornerY, cornerZ); } catch (NoClipboardException | IOException e) { throw new SecurityException("Could not load Clipboard", e); @@ -232,7 +278,7 @@ class PacketProcessor { int blueId = source.rInt(); int redId = source.rInt(); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> BlockTextCreator.pasteTeamNames(blueId, redId)); + execSync(() -> BlockTextCreator.pasteTeamNames(blueId, redId)); } private void scoreboardTitle() throws IOException { @@ -248,23 +294,6 @@ class PacketProcessor { SpectateSystem.getScoreboard().addValue(key, value); } - private void setBlock(int x, int y, int z, int blockState){ - if(Config.ArenaMinX > x || Config.ArenaMaxX < x || Config.ArenaMinZ > z || Config.ArenaMaxZ < z) - return; //Outside of the arena - - if (Config.TechhiderActive && Config.HiddenBlocks.contains(blockState)) { - blockState = Config.ObfuscateWith; - } - IBlockData blockData = Objects.requireNonNull(Block.REGISTRY_ID.fromId(blockState)); - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> { - WorldServer cworld = ((CraftWorld)world).getHandle(); - BlockPosition pos = new BlockPosition(x, y, z); - cworld.removeTileEntity(pos); - cworld.setTypeAndData(pos, blockData, 1042); - cworld.getChunkProvider().flagDirty(pos); - }); - } - private void endSpectating(){ WorldLoader.reloadWorld(); SpectateSystem.getScoreboard().setTitle("§eKein Kampf"); @@ -339,10 +368,10 @@ class PacketProcessor { send(ChatMessageType.SYSTEM); break; case (byte) 0xB0: - pasteSchem(Config.TeamBluePasteX, Config.TeamBlueCornerY, Config.TeamBluePasteZ, Config.TeamBlueRotate, Config.TeamBluePrefix); + pasteSchem(Config.TeamBluePasteX, Config.TeamBlueCornerY, Config.TeamBluePasteZ, Config.TeamBlueCornerX, Config.TeamBlueCornerZ, Config.TeamBlueRotate, Config.TeamBluePrefix); break; case (byte) 0xB1: - pasteSchem(Config.TeamRedPasteX, Config.TeamRedCornerY, Config.TeamRedPasteZ, Config.TeamRedRotate, Config.TeamRedPrefix); + pasteSchem(Config.TeamRedPasteX, Config.TeamRedCornerY, Config.TeamRedPasteZ, Config.TeamRedCornerX, Config.TeamRedCornerZ, Config.TeamRedRotate, Config.TeamRedPrefix); break; case (byte) 0xB2: teams(); @@ -376,9 +405,8 @@ class PacketProcessor { } if(source.isClosed()){ - endSpectating(); - if(!source.async()) - task.cancel(); + Bukkit.getScheduler().runTask(SpectateSystem.get(), this::endSpectating); + task.cancel(); } } } diff --git a/src/de/steamwar/spectatesystem/PlayerSetup.java b/src/de/steamwar/spectatesystem/PlayerSetup.java index 02d6a84..5c6a451 100644 --- a/src/de/steamwar/spectatesystem/PlayerSetup.java +++ b/src/de/steamwar/spectatesystem/PlayerSetup.java @@ -26,6 +26,7 @@ import com.comphenix.protocol.wrappers.EnumWrappers; import com.comphenix.protocol.wrappers.PlayerInfoData; import com.comphenix.protocol.wrappers.WrappedChatComponent; import com.comphenix.protocol.wrappers.WrappedGameProfile; +import de.steamwar.spectatesystem.commands.InspectCommand; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -102,6 +103,9 @@ public class PlayerSetup { } } Bukkit.getScheduler().runTaskLater(SpectateSystem.get(), () -> { + if(InspectCommand.inspecting) + return; + PacketContainer gm1packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.PLAYER_INFO); gm1packet.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE); List playerInfoActions = new ArrayList<>(); diff --git a/src/de/steamwar/spectatesystem/SpectateSystem.java b/src/de/steamwar/spectatesystem/SpectateSystem.java index 76bc293..fbd45b2 100644 --- a/src/de/steamwar/spectatesystem/SpectateSystem.java +++ b/src/de/steamwar/spectatesystem/SpectateSystem.java @@ -19,6 +19,7 @@ package de.steamwar.spectatesystem; +import de.steamwar.spectatesystem.commands.InspectCommand; import de.steamwar.spectatesystem.commands.ReplayCommand; import de.steamwar.spectatesystem.elements.RScoreboard; import de.steamwar.spectatesystem.listener.PlayerListener; @@ -26,14 +27,19 @@ import de.steamwar.spectatesystem.listener.CancelListener; import de.steamwar.spectatesystem.listener.JoinListener; import de.steamwar.spectatesystem.listener.PlayerSeatListener; import de.steamwar.spectatesystem.util.WorldLoader; +import de.steamwar.sql.UserGroup; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import java.io.IOException; +import java.util.EnumSet; +import java.util.Set; import java.util.logging.Level; public class SpectateSystem extends JavaPlugin { + public static final Set allowedGroups = EnumSet.of(UserGroup.Admin, UserGroup.Developer, UserGroup.Moderator); + private static SpectateSystem instance; private static RScoreboard scoreboard; private ConnectionAcceptor acceptor; @@ -53,6 +59,7 @@ public class SpectateSystem extends JavaPlugin { } Bukkit.getPluginCommand("replay").setExecutor(new ReplayCommand()); + Bukkit.getPluginCommand("inspect").setExecutor(new InspectCommand()); WorldLoader.configureForceLoad(); } diff --git a/src/de/steamwar/spectatesystem/commands/InspectCommand.java b/src/de/steamwar/spectatesystem/commands/InspectCommand.java new file mode 100644 index 0000000..fc88afc --- /dev/null +++ b/src/de/steamwar/spectatesystem/commands/InspectCommand.java @@ -0,0 +1,29 @@ +package de.steamwar.spectatesystem.commands; + +import de.steamwar.spectatesystem.SpectateSystem; +import de.steamwar.sql.SteamwarUser; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class InspectCommand implements CommandExecutor { + + public static boolean inspecting = false; + + @Override + public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) { + if(sender instanceof Player){ + Player player = (Player) sender; + SteamwarUser user = SteamwarUser.get(player.getUniqueId()); + if(!SpectateSystem.allowedGroups.contains(user.getUserGroup())){ + player.sendMessage("§eSteam§8War» §cUnbekannter Befehl."); + return false; + } + } + + inspecting = !inspecting; + sender.sendMessage("Inspection: " + inspecting); + return false; + } +} diff --git a/src/de/steamwar/spectatesystem/commands/ReplayCommand.java b/src/de/steamwar/spectatesystem/commands/ReplayCommand.java index 4beea0d..b0e4ed0 100644 --- a/src/de/steamwar/spectatesystem/commands/ReplayCommand.java +++ b/src/de/steamwar/spectatesystem/commands/ReplayCommand.java @@ -20,8 +20,8 @@ package de.steamwar.spectatesystem.commands; import de.steamwar.spectatesystem.FightfileConnection; +import de.steamwar.spectatesystem.SpectateSystem; import de.steamwar.sql.SteamwarUser; -import de.steamwar.sql.UserGroup; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -29,44 +29,29 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; -import java.util.EnumSet; -import java.util.Set; import java.util.logging.Level; public class ReplayCommand implements CommandExecutor { - private static final Set allowedGroups = EnumSet.of(UserGroup.Admin, UserGroup.Developer, UserGroup.Moderator); - private static FightfileConnection fightfileConnection; - @Override public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) { if(sender instanceof Player){ Player player = (Player) sender; SteamwarUser user = SteamwarUser.get(player.getUniqueId()); - if(!allowedGroups.contains(user.getUserGroup())){ + if(!SpectateSystem.allowedGroups.contains(user.getUserGroup())){ player.sendMessage("§eSteam§8War» §cUnbekannter Befehl."); return false; } } - if (fightfileConnection != null && fightfileConnection.isClosed()) { - sender.sendMessage("§eSteam§8War» §cBitte warte bis kein Replay gezeigt wird."); - return false; - } - if(args.length != 1){ sender.sendMessage("§eSteam§8War» §c/replay [Dateipfad]"); return false; } try { - fightfileConnection = new FightfileConnection(new File(args[0] + (args[0].endsWith(".recording") ? "" : ".recording"))); - } catch (FileNotFoundException e) { - Bukkit.getLogger().log(Level.WARNING, "Could not start reading file", e); - sender.sendMessage("§eSteam§8War» §cReplay konnte nicht gefunden werden."); - return false; + new FightfileConnection(new File(args[0] + ".recording")); } catch (IOException e) { Bukkit.getLogger().log(Level.WARNING, "Could not start reading file", e); sender.sendMessage("§eSteam§8War» §cReplay konnte nicht gestartet werden."); diff --git a/src/de/steamwar/spectatesystem/elements/REntity.java b/src/de/steamwar/spectatesystem/elements/REntity.java index 7225343..ff5dedc 100644 --- a/src/de/steamwar/spectatesystem/elements/REntity.java +++ b/src/de/steamwar/spectatesystem/elements/REntity.java @@ -41,7 +41,9 @@ public abstract class REntity { protected REntity(int internalId, Entity entity){ this.internalId = internalId; this.entity = entity; - entities.put(internalId, this); + synchronized(entities){ + entities.put(internalId, this); + } for(Player player : Bukkit.getOnlinePlayers()){ sendToPlayer(player); @@ -49,17 +51,15 @@ public abstract class REntity { } public static void playerJoins(Player player){ - for(REntity entity : entities.values()){ - entity.sendToPlayer(player); - entity.sendLocation(player); + synchronized(entities){ + for(REntity entity : entities.values()){ + entity.sendToPlayer(player); + entity.sendLocation(player); + } } } protected static EntityLiving getShooter(){ - for(REntity entity : entities.values()){ - if(entity.entity instanceof EntityLiving) - return (EntityLiving) entity.entity; - } return ((CraftPlayer)Bukkit.getOnlinePlayers().iterator().next()).getHandle(); } @@ -69,10 +69,12 @@ public abstract class REntity { public static void removeAll(){ int entity_counter = 0; - while(!entities.isEmpty()){ - entity_counter++; - REntity entity = entities.values().iterator().next(); - entity.remove(); + synchronized (entities){ + while(!entities.isEmpty()){ + entity_counter++; + REntity entity = entities.values().iterator().next(); + entity.remove(); + } } System.out.println("Has to remove manually " + entity_counter + " entities!"); } @@ -96,7 +98,9 @@ public abstract class REntity { connection.sendPacket(packet); } Bukkit.getScheduler().runTask(SpectateSystem.get(), entity::die); - entities.remove(internalId); + synchronized (entities){ + entities.remove(internalId); + } } public void sneak(boolean sneaking) { diff --git a/src/de/steamwar/spectatesystem/listener/JoinListener.java b/src/de/steamwar/spectatesystem/listener/JoinListener.java index a29e611..bd76dc2 100644 --- a/src/de/steamwar/spectatesystem/listener/JoinListener.java +++ b/src/de/steamwar/spectatesystem/listener/JoinListener.java @@ -23,18 +23,36 @@ import de.steamwar.scoreboard.SWScoreboard; import de.steamwar.spectatesystem.Config; import de.steamwar.spectatesystem.PlayerSetup; import de.steamwar.spectatesystem.SpectateSystem; +import de.steamwar.spectatesystem.commands.InspectCommand; import de.steamwar.spectatesystem.elements.REntity; +import de.steamwar.sql.SteamwarUser; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerResourcePackStatusEvent; public class JoinListener extends BasicListener { + @EventHandler + public void onLogin(PlayerLoginEvent e){ + Player player = e.getPlayer(); + + if(InspectCommand.inspecting){ + SteamwarUser user = SteamwarUser.get(player.getUniqueId()); + if(!SpectateSystem.allowedGroups.contains(user.getUserGroup())){ + e.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, "§eSteam§8War» §cDerzeit ist das Zuschauen nicht gestattet."); + } + } + } + @EventHandler public void onJoin(PlayerJoinEvent e){ e.setJoinMessage(null); Player player = e.getPlayer(); + + player.setResourcePack("https://steamwar.de/antixray.zip"); player.teleport(Config.SpecSpawn); REntity.playerJoins(player); PlayerSetup.playerJoins(player); @@ -49,4 +67,14 @@ public class JoinListener extends BasicListener { PlayerSetup.playerLeaves(e.getPlayer()); e.setQuitMessage(null); } + + @EventHandler + public void onResourcepack(PlayerResourcePackStatusEvent e){ + if(e.getStatus() == PlayerResourcePackStatusEvent.Status.ACCEPTED || e.getStatus() == PlayerResourcePackStatusEvent.Status.SUCCESSFULLY_LOADED) + return; + + Player player = e.getPlayer(); + player.sendMessage("§eSteam§8War» §cAuf Eventserver kann nur mit dem SteamWar-Resourcepack beigetreten werden"); + player.kickPlayer(null); + } } diff --git a/src/de/steamwar/spectatesystem/listener/PlayerListener.java b/src/de/steamwar/spectatesystem/listener/PlayerListener.java index c63b5cd..baf82e6 100644 --- a/src/de/steamwar/spectatesystem/listener/PlayerListener.java +++ b/src/de/steamwar/spectatesystem/listener/PlayerListener.java @@ -22,6 +22,7 @@ package de.steamwar.spectatesystem.listener; import de.steamwar.spectatesystem.Config; import de.steamwar.spectatesystem.PlayerSetup; import de.steamwar.spectatesystem.SpectateSystem; +import de.steamwar.spectatesystem.commands.InspectCommand; import de.steamwar.spectatesystem.util.Region; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; @@ -53,6 +54,9 @@ public class PlayerListener extends BasicListener { } private void checkMovementInArena(PlayerMoveEvent event, Location to){ + if(InspectCommand.inspecting) + return; + boolean inArenaY = to.getY() + 1.8 <= Config.upperArenaBorder; boolean inBlueArea = inArenaY && Region.isIn2DRange(to, Config.TeamBlueCornerX, Config.TeamBlueCornerZ, Config.SchemsizeX, Config.SchemsizeZ, Config.BorderFromSchematic); boolean inRedArea = inArenaY && Region.isIn2DRange(to, Config.TeamRedCornerX, Config.TeamRedCornerZ, Config.SchemsizeX, Config.SchemsizeZ, Config.BorderFromSchematic); diff --git a/src/de/steamwar/spectatesystem/listener/PlayerSeatListener.java b/src/de/steamwar/spectatesystem/listener/PlayerSeatListener.java index 8b9183d..0e84497 100644 --- a/src/de/steamwar/spectatesystem/listener/PlayerSeatListener.java +++ b/src/de/steamwar/spectatesystem/listener/PlayerSeatListener.java @@ -20,6 +20,8 @@ package de.steamwar.spectatesystem.listener; import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.block.data.Bisected; import org.bukkit.block.data.type.Stairs; import org.bukkit.entity.AbstractArrow; @@ -48,6 +50,9 @@ public class PlayerSeatListener extends BasicListener { if(event.getPlayer().isInsideVehicle()) event.getPlayer().getVehicle().remove(); + + if (event.getClickedBlock().getRelative(0, 1, 0).getType() != Material.AIR) + return; Arrow arrow = (Arrow) event.getPlayer().getWorld().spawnEntity(event.getClickedBlock().getLocation().add(0.5, 0, 0.5), EntityType.ARROW); arrow.setGravity(false); diff --git a/src/de/steamwar/spectatesystem/util/Paster.java b/src/de/steamwar/spectatesystem/util/Paster.java index 06da440..350e76e 100644 --- a/src/de/steamwar/spectatesystem/util/Paster.java +++ b/src/de/steamwar/spectatesystem/util/Paster.java @@ -35,6 +35,7 @@ import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockTypes; import de.steamwar.spectatesystem.Config; +import de.steamwar.spectatesystem.commands.InspectCommand; import de.steamwar.sql.NoClipboardException; import de.steamwar.sql.Schematic; import org.bukkit.Bukkit; @@ -90,7 +91,7 @@ public class Paster { for(int y = 0; y < clipboard.getDimensions().getY(); y++){ for(int z = 0; z < clipboard.getDimensions().getZ(); z++){ BlockVector3 blockPos = minimum.add(x, y, z); - if(Config.HiddenBlockTags.contains(BukkitAdapter.adapt(clipboard.getFullBlock(blockPos).getBlockType()).name())){ + if(!InspectCommand.inspecting && Config.HiddenBlockTags.contains(BukkitAdapter.adapt(clipboard.getFullBlock(blockPos).getBlockType()).name())){ try { clipboard.setBlock(blockPos, obfuscateWith); } catch (WorldEditException e) { diff --git a/src/de/steamwar/spectatesystem/util/WorldLoader.java b/src/de/steamwar/spectatesystem/util/WorldLoader.java index 8228d61..236ee2a 100644 --- a/src/de/steamwar/spectatesystem/util/WorldLoader.java +++ b/src/de/steamwar/spectatesystem/util/WorldLoader.java @@ -19,18 +19,19 @@ package de.steamwar.spectatesystem.util; +import de.steamwar.core.events.ChunkListener; import de.steamwar.spectatesystem.Config; import de.steamwar.spectatesystem.SpectateSystem; import de.steamwar.spectatesystem.elements.REntity; import net.minecraft.server.v1_15_R1.BlockPosition; import net.minecraft.server.v1_15_R1.Blocks; -import net.minecraft.server.v1_15_R1.IBlockData; +import net.minecraft.server.v1_15_R1.Chunk; import net.minecraft.server.v1_15_R1.WorldServer; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.WorldCreator; -import org.bukkit.craftbukkit.v1_15_R1.CraftChunk; import org.bukkit.craftbukkit.v1_15_R1.CraftWorld; +import org.bukkit.entity.Player; public class WorldLoader { private WorldLoader(){} @@ -48,25 +49,21 @@ public class WorldLoader { world.setKeepSpawnInMemory(true); } - public static void reloadWorld(){ - Bukkit.getScheduler().runTask(SpectateSystem.get(), () -> { - REntity.removeAll(); - World backupWorld = new WorldCreator(world.getName() + "-backup").createWorld(); + public static void reloadWorld() { + REntity.removeAll(); + World backupWorld = new WorldCreator(world.getName() + "-backup").createWorld(); - int delay = 1; - Bukkit.getScheduler().runTaskLater(SpectateSystem.get(), () -> fillTeamArea(Config.TeamBlueCornerX, Config.TeamBlueCornerY, Config.TeamBlueCornerZ, Config.SchemsizeX, Config.SchemsizeY, Config.SchemsizeZ), delay++); - Bukkit.getScheduler().runTaskLater(SpectateSystem.get(), () -> fillTeamArea(Config.TeamRedCornerX, Config.TeamRedCornerY, Config.TeamRedCornerZ, Config.SchemsizeX, Config.SchemsizeY, Config.SchemsizeZ), delay++); + fillTeamArea(Config.TeamBlueCornerX, Config.TeamBlueCornerY, Config.TeamBlueCornerZ, Config.SchemsizeX, Config.SchemsizeY, Config.SchemsizeZ); + fillTeamArea(Config.TeamRedCornerX, Config.TeamRedCornerY, Config.TeamRedCornerZ, Config.SchemsizeX, Config.SchemsizeY, Config.SchemsizeZ); - for(int cX = (int) Math.floor(Config.ArenaMinX / 16.0); cX <= (int) Math.floor(Config.ArenaMaxX / 16.0); cX++){ - for(int cZ = (int) Math.floor(Config.ArenaMinZ / 16.0); cZ <= (int) Math.floor(Config.ArenaMaxZ / 16.0); cZ++){ - int finalCX = cX; - int finalCZ = cZ; - Bukkit.getScheduler().runTaskLater(SpectateSystem.get(), () -> reloadChunk(backupWorld, finalCX, finalCZ), delay++); + Bukkit.getScheduler().runTaskLater(SpectateSystem.get(), () -> { + for(int cZ = (int) Math.floor(Config.ArenaMinZ / 16.0); cZ <= (int) Math.floor(Config.ArenaMaxZ / 16.0); cZ++){ + for(int cX = (int) Math.floor(Config.ArenaMinX / 16.0); cX <= (int) Math.floor(Config.ArenaMaxX / 16.0); cX++){ + reloadChunk(backupWorld, cX, cZ); } } - - Bukkit.getScheduler().runTaskLater(SpectateSystem.get(), () -> Bukkit.unloadWorld(world.getName() + "-backup", false), delay); - }); + Bukkit.unloadWorld(world.getName() + "-backup", false); + }, 80); } public static void fillTeamArea(int teamX, int teamY, int teamZ, int sizeX, int sizeY, int sizeZ){ @@ -83,24 +80,17 @@ public class WorldLoader { } } - public static void reloadChunk(World backupWorld, int cX, int cZ){ - WorldServer cworld = ((CraftWorld)world).getHandle(); - WorldServer backup = ((CraftWorld) backupWorld).getHandle(); + public static void reloadChunk(World backup, int x, int z){ + Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(x, z); + Chunk backupChunk = ((CraftWorld) backup).getHandle().getChunkAt(x, z); - net.minecraft.server.v1_15_R1.Chunk cchunk = ((CraftChunk) world.getChunkAt(cX, cZ)).getHandle(); - for(int y = 255; y >= 0; y--){ // y top down to reduce lightning calculations - for(int x = cX * 16; x < (cX + 1) * 16; x++){ - for(int z = cZ * 16; z < (cZ + 1) * 16; z++){ - BlockPosition blockPos = new BlockPosition(x, y, z); - IBlockData backupBlock = backup.getType(blockPos); - if(backupBlock == cworld.getType(blockPos)) - continue; - - cchunk.removeTileEntity(blockPos); - cworld.setTypeAndData(blockPos, backupBlock, 1042); - cworld.getChunkProvider().flagDirty(blockPos); - } - } + System.arraycopy(backupChunk.getSections(), 0, chunk.getSections(), 0, chunk.getSections().length); + chunk.tileEntities.clear(); + chunk.tileEntities.putAll(backupChunk.tileEntities); + chunk.heightMap.clear(); + chunk.heightMap.putAll(backupChunk.heightMap); + for(Player p : Bukkit.getOnlinePlayers()){ + ChunkListener.sendChunk(p, x, z); } } } diff --git a/src/plugin.yml b/src/plugin.yml index 8cd1a66..10295c1 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -5,9 +5,10 @@ version: "1.0" api-version: "1.13" main: de.steamwar.spectatesystem.SpectateSystem load: POSTWORLD -depends: +depend: - SpigotCore - WorldEdit - ProtocolLib commands: - replay: \ No newline at end of file + replay: + inspect: