From 3b4debb6c931339f7d4e7d341ed564f96907712e Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Wed, 8 Jun 2022 03:08:12 +0200 Subject: [PATCH] update for minecraft 1.19 --- nmsutils-plugin/pom.xml | 1 + nmsutils-v1_19_R1/pom.xml | 95 ++++++ .../nmsutils/v1_19_R1/EntityUtilsImpl.java | 299 ++++++++++++++++++ .../nmsutils/v1_19_R1/MiscUtilsImpl.java | 82 +++++ .../nmsutils/v1_19_R1/NMSUtilsImpl.java | 42 +++ ...PathfinderGoalLimitedRandomStrollLand.java | 28 ++ .../nmsutils/v1_19_R1/WorldUtilsImpl.java | 78 +++++ nmsutils/pom.xml | 16 + pom.xml | 12 + 9 files changed, 653 insertions(+) create mode 100644 nmsutils-v1_19_R1/pom.xml create mode 100644 nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/EntityUtilsImpl.java create mode 100644 nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/MiscUtilsImpl.java create mode 100644 nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/NMSUtilsImpl.java create mode 100644 nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/PathfinderGoalLimitedRandomStrollLand.java create mode 100644 nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/WorldUtilsImpl.java diff --git a/nmsutils-plugin/pom.xml b/nmsutils-plugin/pom.xml index c16851b..3e51eb8 100644 --- a/nmsutils-plugin/pom.xml +++ b/nmsutils-plugin/pom.xml @@ -51,6 +51,7 @@ de.cubeside.nmsutils:nmsutils-v1_17_R1_1 de.cubeside.nmsutils:nmsutils-v1_18_R1 de.cubeside.nmsutils:nmsutils-v1_18_R2 + de.cubeside.nmsutils:nmsutils-v1_19_R1 diff --git a/nmsutils-v1_19_R1/pom.xml b/nmsutils-v1_19_R1/pom.xml new file mode 100644 index 0000000..febdc78 --- /dev/null +++ b/nmsutils-v1_19_R1/pom.xml @@ -0,0 +1,95 @@ + + 4.0.0 + nmsutils-v1_19_R1 + + de.cubeside.nmsutils + nmsutils-parent + 0.0.1-SNAPSHOT + + + + io.papermc.paper + paper-api + 1.19-R0.1-SNAPSHOT + provided + + + io.papermc.paper + paper-server + 1.19-R0.1-SNAPSHOT + mojang-mapped + provided + + + ${project.groupId} + nmsutils-core + ${project.version} + provided + + + net.fabricmc + mapping-io + 0.3.0 + provided + + + + + minecraft-repo + https://libraries.minecraft.net/ + + + spigot-repo + https://hub.spigotmc.org/nexus/content/groups/public/ + + + fabric-repo + https://maven.fabricmc.net/ + + + + + + maven-compiler-plugin + 3.8.1 + + 17 + + + + net.md-5 + specialsource-maven-plugin + 1.2.3 + + + package + + remap + + remap-obf + + org.spigotmc:minecraft-server:1.19-R0.1-SNAPSHOT:txt:maps-mojang + true + org.spigotmc:spigot:1.19-R0.1-SNAPSHOT:jar:remapped-mojang + true + remapped-obf + + + + package + + remap + + remap-spigot + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar + org.spigotmc:minecraft-server:1.19-R0.1-SNAPSHOT:csrg:maps-spigot + org.spigotmc:spigot:1.19-R0.1-SNAPSHOT:jar:remapped-obf + + + + + + + diff --git a/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/EntityUtilsImpl.java b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/EntityUtilsImpl.java new file mode 100644 index 0000000..e1d9432 --- /dev/null +++ b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/EntityUtilsImpl.java @@ -0,0 +1,299 @@ +package de.cubeside.nmsutils.v1_19_R1; + +import com.destroystokyo.paper.entity.ai.VanillaGoal; +import de.cubeside.nmsutils.EntityUtils; +import de.cubeside.nmsutils.NMSUtils; +import de.cubeside.nmsutils.util.ReobfHelper; +import java.lang.reflect.Field; +import java.util.function.Function; +import java.util.logging.Level; +import net.minecraft.core.BlockPos; +import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.MoverType; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.ai.goal.FloatGoal; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.entity.Visibility; +import net.minecraft.world.phys.Vec3; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftBat; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftCreature; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftMob; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPiglin; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftShulker; +import org.bukkit.craftbukkit.v1_19_R1.entity.CraftVex; +import org.bukkit.entity.Bat; +import org.bukkit.entity.Creature; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Mob; +import org.bukkit.entity.Vex; +import org.bukkit.util.Vector; + +public class EntityUtilsImpl implements EntityUtils { + private static final Field FIELD_BAT_TARGET = ReobfHelper.getFieldByMojangName(net.minecraft.world.entity.ambient.Bat.class, "targetPosition"); // "bW"; + private static final Field FIELD_ENTITY_TRACKER = ReobfHelper.getFieldByMojangName(Entity.class, "tracker"); // "tracker"; + + private final NMSUtilsImpl nmsUtils; + + public EntityUtilsImpl(NMSUtilsImpl nmsUtils) { + this.nmsUtils = nmsUtils; + } + + @Override + public NMSUtils getNMSUtils() { + return nmsUtils; + } + + @Override + public void clearAI(org.bukkit.entity.Entity entity) { + if (entity instanceof Mob) { + nmsUtils.getPlugin().getServer().getMobGoals().removeAllGoals((Mob) entity); + } + } + + @Override + public void addGoalFloat(Mob mob) { + if (!Bukkit.getMobGoals().hasGoal(mob, VanillaGoal.FLOAT)) { + net.minecraft.world.entity.Mob h = ((CraftMob) mob).getHandle(); + h.goalSelector.addGoal(1, new FloatGoal(h)); + } + } + + @Override + public void addGoalLimitedStrollLand(Creature mob, double velocity, Function checkTargetFunction) { + PathfinderMob h = ((CraftCreature) mob).getHandle(); + h.goalSelector.addGoal(7, new PathfinderGoalLimitedRandomStrollLand(h, velocity, checkTargetFunction)); + } + + @Override + public int getShulkerOpenState(org.bukkit.entity.Entity shulker) { + try { + if (shulker.getType() != EntityType.SHULKER) { + return 0; + } + CraftShulker cs = (CraftShulker) shulker; + return cs.getHandle().getRawPeekAmount(); + } catch (Exception e) { + nmsUtils.getPlugin().getLogger().log(Level.SEVERE, "Could not get shulker open state", e); + } + return 0; + } + + @Override + public void setShulkerOpenState(org.bukkit.entity.Entity shulker, int state) { + try { + if (shulker.getType() != EntityType.SHULKER) { + return; + } + state = Math.max(0, Math.min(Byte.MAX_VALUE, state)); + CraftShulker cs = (CraftShulker) shulker; + cs.getHandle().setRawPeekAmount(state); + } catch (Exception e) { + nmsUtils.getPlugin().getLogger().log(Level.SEVERE, "Could not set shulker open state", e); + } + } + + @Override + public boolean isPiglinDancing(org.bukkit.entity.Entity piglin) { + try { + if (piglin.getType() != EntityType.PIGLIN) { + return false; + } + CraftPiglin cs = (CraftPiglin) piglin; + return cs.getHandle().isDancing(); + } catch (Exception e) { + nmsUtils.getPlugin().getLogger().log(Level.SEVERE, "Could not get piglin dancing state", e); + } + return false; + } + + @Override + public void setPiglinDancing(org.bukkit.entity.Entity piglin, boolean dancing) { + try { + if (piglin.getType() != EntityType.PIGLIN) { + return; + } + CraftPiglin cs = (CraftPiglin) piglin; + cs.getHandle().setDancing(dancing); + } catch (Exception e) { + nmsUtils.getPlugin().getLogger().log(Level.SEVERE, "Could not set piglin dancing state", e); + } + } + + @Override + public void sendEntityPositionUpdate(org.bukkit.entity.Entity entity) { + Entity handle = ((CraftEntity) entity).getHandle(); + try { + ChunkMap.TrackedEntity ete = (ChunkMap.TrackedEntity) FIELD_ENTITY_TRACKER.get(handle); + if (ete != null) { + ClientboundTeleportEntityPacket positionPacket = new ClientboundTeleportEntityPacket(handle); + ete.seenBy.stream().forEach(viewer -> { + viewer.send(positionPacket); + }); + } + } catch (ReflectiveOperationException e) { + nmsUtils.getPlugin().getLogger().log(Level.SEVERE, "Could not send teleport packet", e); + } + } + + @Override + public void moveEntity(org.bukkit.entity.Entity e, double x, double y, double z) { + Entity handle = ((CraftEntity) e).getHandle(); + handle.move(MoverType.SELF, new Vec3(x, y, z)); + } + + @Override + public void moveEntity(org.bukkit.entity.Entity e, Vector v) { + moveEntity(e, v.getX(), v.getY(), v.getZ()); + } + + @Override + public void setEntityHeadRotation(org.bukkit.entity.Entity e, float headRotation) { + Entity handle = ((CraftEntity) e).getHandle(); + if (handle instanceof LivingEntity) { + // required for goats + ((LivingEntity) handle).yHeadRot = headRotation; + } else { + handle.setYHeadRot(headRotation); + } + } + + @Override + public float getEntityHeadRotation(org.bukkit.entity.Entity e) { + Entity handle = ((CraftEntity) e).getHandle(); + return handle.getYHeadRot(); + } + + @Override + public void setEntityYaw(org.bukkit.entity.Entity e, float yaw) { + Entity handle = ((CraftEntity) e).getHandle(); + handle.setYRot(yaw); + } + + @Override + public float getEntityYaw(org.bukkit.entity.Entity e) { + Entity handle = ((CraftEntity) e).getHandle(); + return handle.getYRot(); + } + + @Override + public void setEntityPitch(org.bukkit.entity.Entity e, float pitch) { + Entity handle = ((CraftEntity) e).getHandle(); + handle.setXRot(pitch); + } + + @Override + public float getEntityPitch(org.bukkit.entity.Entity e) { + Entity handle = ((CraftEntity) e).getHandle(); + return handle.getXRot(); + } + + @Override + public void setEntityNavigationTarget(org.bukkit.entity.Entity entity, Location target, double speed) { + if (entity instanceof Bat) { + try { + FIELD_BAT_TARGET.set(((CraftBat) entity).getHandle(), new BlockPos(target.getX(), target.getY(), target.getZ())); + } catch (ReflectiveOperationException e) { + nmsUtils.getPlugin().getLogger().log(Level.SEVERE, "could not set field", e); + } + } else if (entity instanceof Vex) { + net.minecraft.world.entity.monster.Vex entityVex = ((CraftVex) entity).getHandle(); + entityVex.getMoveControl().setWantedPosition(target.getX(), target.getY(), target.getZ(), speed); + if (entityVex.getTarget() == null) { + entityVex.getLookControl().setLookAt(target.getX(), target.getY(), target.getZ(), 180, 20); + } + } else if (entity instanceof CraftMob) { + ((CraftMob) entity).getHandle().getNavigation().moveTo(target.getX(), target.getY(), target.getZ(), speed); + } else { + throw new IllegalArgumentException("Cannot set the navigation target for this mob"); + } + } + + @Override + public void setEntityLeftHanded(org.bukkit.entity.Entity ent, boolean left) { + Entity nmsEntity = ((CraftEntity) ent).getHandle(); + if (nmsEntity instanceof net.minecraft.world.entity.Mob mob) { + mob.setLeftHanded(left); + } + } + + @Override + public boolean isEntityLeftHanded(org.bukkit.entity.Entity ent) { + Entity nmsEntity = ((CraftEntity) ent).getHandle(); + if (nmsEntity instanceof net.minecraft.world.entity.Mob mob) { + return mob.isLeftHanded(); + } + return false; + } + + @Override + public boolean isEntityInvisible(org.bukkit.entity.Entity entity) { + Entity nmsEntity = ((CraftEntity) entity).getHandle(); + return nmsEntity.isInvisible(); + } + + @Override + public void setEntityInvisible(org.bukkit.entity.Entity entity, boolean invisible) { + Entity nmsEntity = ((CraftEntity) entity).getHandle(); + nmsEntity.setInvisible(invisible); + } + + @Override + public boolean hasEntityNoClip(org.bukkit.entity.Entity entity) { + Entity nmsEntity = ((CraftEntity) entity).getHandle(); + return nmsEntity.noPhysics; + } + + @Override + public void setEntityNoClip(org.bukkit.entity.Entity entity, boolean noClip) { + Entity nmsEntity = ((CraftEntity) entity).getHandle(); + nmsEntity.noPhysics = noClip; + } + + @Override + public boolean areChunkEntitiesLoaded(Chunk c) { + return ((CraftWorld) c.getWorld()).getHandle().areEntitiesLoaded(ChunkPos.asLong(c.getX(), c.getZ())); + } + + @Override + public void loadChunkEntities(Chunk c) { + int x = c.getX(); + int z = c.getZ(); + World world = c.getWorld(); + if (!world.isChunkLoaded(x, z)) { + world.getChunkAt(x, z); + } + + if (areChunkEntitiesLoaded(c)) { + return; + } + ServerLevel serverLevel = ((CraftWorld) world).getHandle(); + serverLevel.entityManager.updateChunkStatus(new ChunkPos(x, z), Visibility.TRACKED); + // now wait until entities are loaded + if (!areChunkEntitiesLoaded(c)) { + serverLevel.getServer().managedBlock(() -> { + if (areChunkEntitiesLoaded(c)) { + return true; + } + // process chunk inbox + serverLevel.entityManager.tick(); + return areChunkEntitiesLoaded(c); + }); + } + } + + @Override + public void setOnGround(org.bukkit.entity.Entity entity, boolean onGround) { + Entity nmsEntity = ((CraftEntity) entity).getHandle(); + nmsEntity.setOnGround(onGround); + } +} diff --git a/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/MiscUtilsImpl.java b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/MiscUtilsImpl.java new file mode 100644 index 0000000..1237900 --- /dev/null +++ b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/MiscUtilsImpl.java @@ -0,0 +1,82 @@ +package de.cubeside.nmsutils.v1_19_R1; + +import de.cubeside.nmsutils.MiscUtils; +import de.cubeside.nmsutils.NMSUtils; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; +import net.minecraft.world.level.block.state.BlockBehaviour.BlockStateBase; +import net.minecraft.world.level.block.state.BlockBehaviour.Properties; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.MaterialColor; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_19_R1.util.CraftMagicNumbers; + +public class MiscUtilsImpl implements MiscUtils { + private final NMSUtilsImpl nmsUtils; + + private Field fieldBlockBehaviour_properties; + private MaterialColor transparentColor; + private Field fieldBlockStateBase_materialColor; + + public MiscUtilsImpl(NMSUtilsImpl nmsUtils) { + this.nmsUtils = nmsUtils; + } + + @Override + public NMSUtils getNMSUtils() { + return nmsUtils; + } + + @Override + public void setBlockMapColorTransparent(Material m) { + if (fieldBlockBehaviour_properties == null) { + Class classBlockProperties = BlockBehaviour.Properties.class; + Class classBlockBehaviour = BlockBehaviour.class; + fieldBlockBehaviour_properties = null; + for (Field f : classBlockBehaviour.getDeclaredFields()) { + if (f.getType() == classBlockProperties) { + fieldBlockBehaviour_properties = f; + fieldBlockBehaviour_properties.setAccessible(true); + } + } + if (fieldBlockBehaviour_properties == null) { + throw new IllegalStateException("Could not find block properties field!"); + } + + Class classBlockStateBase = BlockBehaviour.BlockStateBase.class; + for (Field f : classBlockStateBase.getDeclaredFields()) { + if (f.getType() == MaterialColor.class) { + fieldBlockStateBase_materialColor = f; + fieldBlockStateBase_materialColor.setAccessible(true); + } + } + if (fieldBlockStateBase_materialColor == null) { + throw new IllegalStateException("Could not find BlockStateBase materialColor field!"); + } + + try { + Constructor constructorMaterialColor = MaterialColor.class.getDeclaredConstructor(int.class, int.class); + constructorMaterialColor.setAccessible(true); + transparentColor = constructorMaterialColor.newInstance(0, 0); + } catch (ReflectiveOperationException e) { + throw new IllegalStateException("Could not create custom transparent MaterialColor!"); + } + } + + if (!m.isBlock()) { + throw new IllegalArgumentException("Material must be a block"); + } + Block b = CraftMagicNumbers.getBlock(m); + try { + BlockBehaviour.Properties properties = (Properties) fieldBlockBehaviour_properties.get(b); + properties.color(transparentColor); + for (BlockState state : b.getStateDefinition().getPossibleStates()) { + fieldBlockStateBase_materialColor.set(state, transparentColor); + } + } catch (IllegalAccessException e) { + throw new IllegalStateException("Could not set the MaterialColor!"); + } + } +} diff --git a/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/NMSUtilsImpl.java b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/NMSUtilsImpl.java new file mode 100644 index 0000000..56b9567 --- /dev/null +++ b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/NMSUtilsImpl.java @@ -0,0 +1,42 @@ +package de.cubeside.nmsutils.v1_19_R1; + +import de.cubeside.nmsutils.EntityUtils; +import de.cubeside.nmsutils.MiscUtils; +import de.cubeside.nmsutils.NMSUtils; +import de.cubeside.nmsutils.WorldUtils; +import org.bukkit.plugin.Plugin; + +public class NMSUtilsImpl implements NMSUtils { + private final Plugin plugin; + private EntityUtils entityUtilsImpl; + private WorldUtilsImpl worldUtilsImpl; + private MiscUtilsImpl miscUtilsImpl; + + public NMSUtilsImpl(Plugin plugin) { + this.plugin = plugin; + this.entityUtilsImpl = new EntityUtilsImpl(this); + this.worldUtilsImpl = new WorldUtilsImpl(this); + this.miscUtilsImpl = new MiscUtilsImpl(this); + // Remapper.foo(net.minecraft.world.entity.ambient.Bat.class); + } + + @Override + public Plugin getPlugin() { + return plugin; + } + + @Override + public EntityUtils getEntityUtils() { + return entityUtilsImpl; + } + + @Override + public WorldUtils getWorldUtils() { + return worldUtilsImpl; + } + + @Override + public MiscUtils getMiscUtils() { + return miscUtilsImpl; + } +} diff --git a/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/PathfinderGoalLimitedRandomStrollLand.java b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/PathfinderGoalLimitedRandomStrollLand.java new file mode 100644 index 0000000..e8ab326 --- /dev/null +++ b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/PathfinderGoalLimitedRandomStrollLand.java @@ -0,0 +1,28 @@ +package de.cubeside.nmsutils.v1_19_R1; + +import java.util.function.Function; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.ai.goal.RandomStrollGoal; +import net.minecraft.world.phys.Vec3; +import org.bukkit.util.Vector; + +public class PathfinderGoalLimitedRandomStrollLand extends RandomStrollGoal { + + private Function checkVectorFunction; + // private EntityCreature entity; + + public PathfinderGoalLimitedRandomStrollLand(PathfinderMob entity, double velocity, Function checkVectorFunction) { + super(entity, velocity, 1, false); + // this.entity = entity; + this.checkVectorFunction = checkVectorFunction; + } + + @Override + protected Vec3 getPosition() { + Vec3 base = super.getPosition(); + if (base == null || checkVectorFunction.apply(org.bukkit.craftbukkit.v1_19_R1.util.CraftVector.toBukkit(base)) != Boolean.TRUE) { + base = null; + } + return base; + } +} diff --git a/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/WorldUtilsImpl.java b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/WorldUtilsImpl.java new file mode 100644 index 0000000..b13def7 --- /dev/null +++ b/nmsutils-v1_19_R1/src/main/java/de/cubeside/nmsutils/v1_19_R1/WorldUtilsImpl.java @@ -0,0 +1,78 @@ +package de.cubeside.nmsutils.v1_19_R1; + +import de.cubeside.nmsutils.WorldUtils; +import java.util.ArrayList; +import java.util.logging.Level; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; +import org.bukkit.entity.Player; + +public class WorldUtilsImpl implements WorldUtils { + private final NMSUtilsImpl nmsUtils; + + public WorldUtilsImpl(NMSUtilsImpl nmsUtils) { + this.nmsUtils = nmsUtils; + } + + @Override + public void saveWorldNow(World world) { + world.save(); + + CraftWorld craftWorld = (CraftWorld) world; + ServerLevel handle = craftWorld.getHandle(); + try { + handle.save(null, true, false); + } catch (Exception e) { + Bukkit.getLogger().log(Level.SEVERE, "Exception while saving world", e); + } + } + + @Override + public void forceUnloadWorldWithoutSaving(World world, Location playerTarget) { + // final long t0 = System.currentTimeMillis(); + // String worldName = world.getName(); + + if (playerTarget.getWorld() == null || playerTarget.getWorld() == world) { + throw new IllegalArgumentException("Valid target world required"); + } + // move players out of this world + try { + for (Player p : world.getPlayers()) { + if (p.isDead()) { + p.spigot().respawn(); + } + if (p.getWorld() == world) { + p.teleport(playerTarget); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + // remove broken players + CraftWorld craftWorld = (CraftWorld) world; + ServerLevel handle = craftWorld.getHandle(); + if (!handle.players().isEmpty()) { + for (ServerPlayer human : new ArrayList<>(handle.players())) { + kickPlayer((human.getBukkitEntity()), "Connection lost"); + } + handle.players().clear(); + } + + // unload the now empty world from the server + if (!nmsUtils.getPlugin().getServer().unloadWorld(world, false)) { + throw new IllegalStateException("Could not unload world"); + } + + // long t = System.currentTimeMillis(); + // nmsUtils.getPlugin().getLogger().info("Unloading world " + worldName + " completed in " + (t - t0) + "ms."); + } + + @SuppressWarnings("deprecation") + private void kickPlayer(Player player, String message) { + player.kickPlayer(message); + } +} diff --git a/nmsutils/pom.xml b/nmsutils/pom.xml index 8a8e200..fd77a58 100644 --- a/nmsutils/pom.xml +++ b/nmsutils/pom.xml @@ -15,6 +15,22 @@ + + v1_19 + + true + + all + + + + + ${project.groupId} + nmsutils-v1_19_R1 + ${project.version} + + + v1_18_2 diff --git a/pom.xml b/pom.xml index f778d57..02601db 100644 --- a/pom.xml +++ b/pom.xml @@ -24,6 +24,18 @@ + + v1_19 + + true + + all + + + + nmsutils-v1_19_R1 + + v1_18_2