From b73052c5e068ef70be102d0a4edf7e0d3e28a9f5 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sat, 20 Mar 2021 12:01:27 +0100 Subject: [PATCH] Fast WorldReset, reduce spawned tasks, fix schemcoloring --- .../spectatesystem/PacketProcessor.java | 113 +++++++++++------- .../spectatesystem/util/WorldLoader.java | 58 ++++----- 2 files changed, 92 insertions(+), 79 deletions(-) diff --git a/src/de/steamwar/spectatesystem/PacketProcessor.java b/src/de/steamwar/spectatesystem/PacketProcessor.java index 737bb7a..cbcb9d0 100644 --- a/src/de/steamwar/spectatesystem/PacketProcessor.java +++ b/src/de/steamwar/spectatesystem/PacketProcessor.java @@ -43,6 +43,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 +55,49 @@ 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) { + runnable.run(); + } + 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 +106,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 +142,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 +155,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 +195,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 (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 +219,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 +236,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 +247,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 +273,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 +289,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 +363,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 +400,8 @@ class PacketProcessor { } if(source.isClosed()){ - endSpectating(); - if(!source.async()) - task.cancel(); + execSync(() -> endSpectating()); + task.cancel(); } } } diff --git a/src/de/steamwar/spectatesystem/util/WorldLoader.java b/src/de/steamwar/spectatesystem/util/WorldLoader.java index 8228d61..2dc3d64 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); + }, 10); } 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); } } }