Fast WorldReset, reduce spawned tasks, fix schemcoloring #12
@ -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,53 @@ class PacketProcessor {
|
||||
|
||||
private final PacketSource source;
|
||||
private final BukkitTask task;
|
||||
private final LinkedList<Runnable> 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 +110,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 +146,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 +159,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 +199,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 +223,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 +240,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 +251,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 +277,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 +293,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 +367,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 +404,8 @@ class PacketProcessor {
|
||||
}
|
||||
|
||||
if(source.isClosed()){
|
||||
endSpectating();
|
||||
if(!source.async())
|
||||
task.cancel();
|
||||
Bukkit.getScheduler().runTask(SpectateSystem.get(), this::endSpectating);
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren