diff --git a/gradle.properties b/gradle.properties index cdcfb353..f687e0c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,6 @@ version=1.0.0-SNAPSHOT description=Minecraft world management plugin org.gradle.parallel=true -org.gradle.jvmargs=-Xmx512m +org.gradle.jvmargs=-Xmx2G org.gradle.java.installations.auto-download=false org.gradle.caching=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3905cdd6..d07d0fe8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,9 +3,9 @@ cloud-build-logic = "0.0.3" ktlint = "0.50.0" checkstyle = "10.12.5" kotlin = "1.9.20" -shadow = "9.0.0-beta8" -paperweight = "2.0.0-beta.17" -run-paper = "2.3.1" +shadow = "9.4.1" +paperweight = "2.0.0-beta.21" +run-paper = "3.0.2" pluginyml = "0.6.0" # Platforms diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 002b867c..c61a118f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/hyperverse-core/build.gradle.kts b/hyperverse-core/build.gradle.kts index 3758e662..2d6a9917 100644 --- a/hyperverse-core/build.gradle.kts +++ b/hyperverse-core/build.gradle.kts @@ -44,13 +44,8 @@ dependencies { implementation("net.kyori:adventure-text-minimessage:4.14.0") implementation(projects.hyperverseNmsUnsupported) - runtimeOnly(projects.hyperverseNms1206) - runtimeOnly(projects.hyperverseNms121) - runtimeOnly(projects.hyperverseNms1213) - runtimeOnly(projects.hyperverseNms1214) - runtimeOnly(projects.hyperverseNms1215) - runtimeOnly(projects.hyperverseNms1216) - runtimeOnly(projects.hyperverseNms1217) + runtimeOnly(projects.hyperverseNms261) + runtimeOnly(projects.hyperverseNms262) } bukkit { @@ -95,7 +90,9 @@ bukkit { } } } - +java { + disableAutoTargetJvm() +} tasks { processResources { filesMatching("plugin.yml") { @@ -106,13 +103,8 @@ tasks { shadowJar { minimize { exclude(project(":hyperverse-nms-unsupported")) - exclude(project(":hyperverse-nms-1-20-6")) - exclude(project(":hyperverse-nms-1-21")) - exclude(project(":hyperverse-nms-1-21-3")) - exclude(project(":hyperverse-nms-1-21-4")) - exclude(project(":hyperverse-nms-1-21-5")) - exclude(project(":hyperverse-nms-1-21-6")) - exclude(project(":hyperverse-nms-1-21-7")) + exclude(project(":hyperverse-nms-26-1")) + exclude(project(":hyperverse-nms-26-2")) } mergeServiceFiles() @@ -149,7 +141,7 @@ tasks { } runServer { - java.toolchain.languageVersion.set(JavaLanguageVersion.of(21)) - minecraftVersion("1.21.7") + java.toolchain.languageVersion.set(JavaLanguageVersion.of(25)) + minecraftVersion("26.2") } } diff --git a/hyperverse-core/src/main/java/org/incendo/hyperverse/Hyperverse.java b/hyperverse-core/src/main/java/org/incendo/hyperverse/Hyperverse.java index 2c1ea584..e0be6e7b 100644 --- a/hyperverse-core/src/main/java/org/incendo/hyperverse/Hyperverse.java +++ b/hyperverse-core/src/main/java/org/incendo/hyperverse/Hyperverse.java @@ -93,13 +93,8 @@ public final class Hyperverse extends JavaPlugin implements HyperverseAPI, Liste private final ServicePipeline servicePipeline = ServicePipeline.builder().build(); private final List supportedVersions = List.of( - Version.parseMinecraft("1.20.6"), - Version.parseMinecraft("1.21.1"), - Version.parseMinecraft("1.21.3"), - Version.parseMinecraft("1.21.4"), - Version.parseMinecraft("1.21.5"), - Version.parseMinecraft("1.21.6"), - Version.parseMinecraft("1.21.7") + Version.parseMinecraft("26.1.2"), + Version.parseMinecraft("26.2") ); private WorldManager worldManager; diff --git a/hyperverse-core/src/main/java/org/incendo/hyperverse/platform/ReflectionPlatformProvider.java b/hyperverse-core/src/main/java/org/incendo/hyperverse/platform/ReflectionPlatformProvider.java index 304af39a..9ef79dd6 100644 --- a/hyperverse-core/src/main/java/org/incendo/hyperverse/platform/ReflectionPlatformProvider.java +++ b/hyperverse-core/src/main/java/org/incendo/hyperverse/platform/ReflectionPlatformProvider.java @@ -32,13 +32,25 @@ public ReflectionPlatformProvider(@NotNull final Version version) { @Override public @NotNull Class providePlatform() throws PlatformProvisionException { - String expectedPackage = this.minecraftVersion.original().toLowerCase(Locale.ENGLISH).replace('.', '_'); + var data = this.minecraftVersion.versionData(); + + String expectedPackage; + if (data.patch() == 0) { + expectedPackage = data.major() + "_" + data.minor(); + } else { + expectedPackage = data.major() + "_" + data.minor() + "_" + data.patch(); + } + String packageName = "org.incendo.hyperverse.platform.v" + expectedPackage; + try { Class clazz = Class.forName(packageName + ".NMSImpl"); return clazz.asSubclass(NMS.class); } catch (ReflectiveOperationException ex) { - throw new PlatformProvisionException("Could not provide platform for version: " + this.minecraftVersion + "!", ex); + throw new PlatformProvisionException( + "Could not provide platform for version: " + this.minecraftVersion + "!", + ex + ); } } diff --git a/hyperverse-core/src/main/java/org/incendo/hyperverse/util/versioning/Version.java b/hyperverse-core/src/main/java/org/incendo/hyperverse/util/versioning/Version.java index ba07b792..9359f537 100644 --- a/hyperverse-core/src/main/java/org/incendo/hyperverse/util/versioning/Version.java +++ b/hyperverse-core/src/main/java/org/incendo/hyperverse/util/versioning/Version.java @@ -32,21 +32,26 @@ public record Version(@NotNull String original, @NotNull VersionData versionData public static final Pattern SEMVER_PATTERN = Pattern.compile( "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"); - public static @NotNull Version parseMinecraft(@NotNull final String version) throws IllegalArgumentException { - String[] split = version.split("\\."); - if (split.length < 2) { + public static @NotNull Version parseMinecraft(@NotNull final String version) + throws IllegalArgumentException { + + // Extract only x.y or x.y.z from beginning + Matcher matcher = Pattern.compile("^(\\d+)\\.(\\d+)(?:\\.(\\d+))?") + .matcher(version); + + if (!matcher.find()) { throw new IllegalArgumentException("Invalid minecraft version: " + version); } - if (split.length == 2) { - StringJoiner joiner = new StringJoiner("."); - // insert a .0 to make it correctly formatted - joiner.add(split[0]); - joiner.add("0"); - joiner.add(split[1]); - Version formatted = parseSemVer(joiner.toString()); - return new Version(version, formatted.versionData()); + + String major = matcher.group(1); + String minor = matcher.group(2); + String patch = matcher.group(3); + + if (patch == null) { + patch = "0"; } - return parseSemVer(version); + + return parseSemVer(major + "." + minor + "." + patch); } public static @NotNull Version parseSemVer(@NotNull final String version) throws IllegalArgumentException { diff --git a/hyperverse-nms-1-20-6/src/main/java/org/incendo/hyperverse/platform/v1_20_6/NMSImpl.java b/hyperverse-nms-1-20-6/src/main/java/org/incendo/hyperverse/platform/v1_20_6/NMSImpl.java deleted file mode 100644 index 2910f092..00000000 --- a/hyperverse-nms-1-20-6/src/main/java/org/incendo/hyperverse/platform/v1_20_6/NMSImpl.java +++ /dev/null @@ -1,248 +0,0 @@ -// -// Hyperverse - A minecraft world management plugin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -package org.incendo.hyperverse.platform.v1_20_6; - -import co.aikar.taskchain.TaskChainFactory; -import com.google.inject.Inject; -import io.papermc.lib.PaperLib; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; -import java.util.Optional; - -import net.minecraft.BlockUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.border.WorldBorder; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.entity.EntityLookup; -import net.minecraft.world.level.entity.PersistentEntitySectionManager; -import net.minecraft.world.level.portal.PortalForcer; -import net.minecraft.world.phys.Vec3; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.Logger; -import org.apache.logging.log4j.core.filter.RegexFilter; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.incendo.hyperverse.util.HyperConfigShouldGroupProfiles; -import org.incendo.hyperverse.util.NMS; - -@SuppressWarnings("unused") -public class NMSImpl implements NMS { - - private final TaskChainFactory taskFactory; - private Field entitySectionManager; - private Field entityLookup; - private org.apache.logging.log4j.core.Logger worldServerLogger; - - @Inject public NMSImpl(final TaskChainFactory taskFactory, final @HyperConfigShouldGroupProfiles boolean hyperConfiguration) { - this.taskFactory = taskFactory; - if (hyperConfiguration) { - try { - final Field field = ServerLevel.class.getDeclaredField("LOGGER"); - field.setAccessible(true); - this.worldServerLogger = (Logger) field.get(null); - } catch (final Exception e) { - e.printStackTrace(); - } - try { - final RegexFilter regexFilter = RegexFilter - .createFilter("[\\S\\s]*Force-added player with duplicate UUID[\\S\\s]*", null, false, - Filter.Result.DENY, Filter.Result.ACCEPT); - this.worldServerLogger.addFilter(regexFilter); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - - @Override @Nullable public Location getOrCreateNetherPortal(@NotNull final org.bukkit.entity.Entity entity, - @NotNull final Location origin) { - final ServerLevel worldServer = Objects.requireNonNull(((CraftWorld) origin.getWorld()).getHandle()); - final PortalForcer portalTravelAgent = Objects.requireNonNull(worldServer.getPortalForcer()); - final Entity nmsEntity = Objects.requireNonNull(((CraftEntity) entity).getHandle()); - final BlockPos blockPosition = new BlockPos(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); - final WorldBorder worldBorder = worldServer.getWorldBorder(); - Optional portalShape = Objects.requireNonNull(portalTravelAgent, "travel agent") - .findPortalAround(Objects.requireNonNull(blockPosition, "position"), worldBorder,128); - if (portalShape.isEmpty()) { - portalShape = portalTravelAgent.createPortal(blockPosition, nmsEntity.getDirection().getAxis(), nmsEntity, 16); - } - if (portalShape.isEmpty()) { - return null; - } - final BlockUtil.FoundRectangle rectangle = portalShape.get(); - return new Location(origin.getWorld(), rectangle.minCorner.getX() + 1, rectangle.minCorner.getY() - 1, - rectangle.minCorner.getZ() + 1); - } - - @Override @Nullable public Location getDimensionSpawn(@NotNull final Location origin) { - if (Objects.requireNonNull(origin.getWorld()).getEnvironment() - == World.Environment.THE_END) { - return new Location(origin.getWorld(), 100, 50, 0); - } - return origin.getWorld().getSpawnLocation(); - } - - @Override public void writePlayerData(@NotNull final Player player, @NotNull final Path file) { - final CompoundTag playerTag = new CompoundTag(); - final net.minecraft.world.entity.player.Player entityPlayer = ((CraftPlayer) player).getHandle(); - entityPlayer.save(playerTag); - - if (!playerTag.contains("hyperverse")) { - playerTag.put("hyperverse", new CompoundTag()); - } - final CompoundTag hyperverse = playerTag.getCompound("hyperverse"); - hyperverse.putLong("writeTime", System.currentTimeMillis()); - hyperverse.putString("version", Bukkit.getPluginManager().getPlugin("Hyperverse").getDescription().getVersion()); - - taskFactory.newChain().async(() -> { - try (final OutputStream outputStream = Files.newOutputStream(file)) { - NbtIo.writeCompressed(playerTag, outputStream); - } catch (final Exception e) { - e.printStackTrace(); - } - }).execute(); - } - - @Override public void readPlayerData(@NotNull final Player player, @NotNull final Path file, @NotNull final Runnable whenDone) { - final Location originLocation = player.getLocation().clone(); - taskFactory.newChain().asyncFirst(() -> { - try (final InputStream inputStream = Files.newInputStream(file)) { - return Optional.of(NbtIo.readCompressed(inputStream, NbtAccounter.unlimitedHeap())); - } catch (final Exception e) { - e.printStackTrace(); - } - return Optional.empty(); - }).syncLast((optionalCompound) -> { - if (!optionalCompound.isPresent()) { - return; - } - final CompoundTag compound = (CompoundTag) optionalCompound.get(); - PaperLib.getChunkAtAsync(originLocation).thenAccept(chunk -> { - // Health and hunger don't update properly, so we - // give them a little help - final float health = compound.getFloat("Health"); - final int foodLevel = compound.getInt("foodLevel"); - - // Restore bed spawn - final String spawnWorld = compound.getString("SpawnWorld"); - final int spawnX = compound.getInt("SpawnX"); - final int spawnY = compound.getInt("SpawnY"); - final int spawnZ = compound.getInt("SpawnZ"); - final Location spawnLocation = new Location(Bukkit.getWorld(spawnWorld), spawnX, - spawnY, spawnZ); - - final ServerPlayer entityPlayer = ((CraftPlayer) player).getHandle(); - - // We re-write the extra Bukkit data as to not - // mess up the profile - ((CraftPlayer) player).setExtraData(compound); - // Set the position to the player's current position - Vec3 pos = entityPlayer.position(); - compound.put("Pos", doubleList(pos.x, pos.y, pos.z)); - // Set the world to the player's current world - compound.putString("world", player.getWorld().getName()); - // Store persistent values - ((CraftPlayer) player).storeBukkitValues(compound); - - // We start by doing a total reset - entityPlayer.reset(); - entityPlayer.load(compound); - - entityPlayer.effectsDirty = true; - entityPlayer.onUpdateAbilities(); - player.teleport(originLocation); - - final ServerLevel worldServer = ((CraftWorld) originLocation.getWorld()).getHandle(); - final DimensionType dimensionManager = worldServer.dimensionType(); - - // Prevent annoying message - // Spigot-obf = decouple() - entityPlayer.unRide(); - worldServer.removePlayerImmediately(entityPlayer, Entity.RemovalReason.CHANGED_DIMENSION); - // worldServer.removePlayer above should remove the player from the - // map, but that doesn't always happen. This is a last effort - // attempt to prevent the annoying "Force re-added" message - // from appearing - try { - if (this.entitySectionManager == null) { - this.entitySectionManager = worldServer.getClass().getDeclaredField("entityManager"); - this.entitySectionManager.setAccessible(true); - } - final PersistentEntitySectionManager esm = (PersistentEntitySectionManager) this.entitySectionManager.get(worldServer); - if (this.entityLookup == null) { - this.entityLookup = esm.getClass().getDeclaredField("visibleEntityStorage"); - } - final EntityLookup lookup = (EntityLookup) this.entityLookup.get(esm); - lookup.remove(entityPlayer); - } catch (final NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } - - // pre 1.18 code = PlayerList#moveToWorld - entityPlayer.server.getPlayerList().remove(entityPlayer); - worldServer.getServer().getPlayerList().respawn(entityPlayer, worldServer, true, originLocation, true, PlayerRespawnEvent.RespawnReason.PLUGIN); - - // Apply health and foodLevel - player.setHealth(health); - player.setFoodLevel(foodLevel); - player.setPortalCooldown(40); - player.setBedSpawnLocation(spawnLocation, true); - }); - }).execute(whenDone); - } - - @Override @Nullable public Location findBedRespawn(@NotNull final Location spawnLocation) { - final CraftWorld craftWorld = (CraftWorld) spawnLocation.getWorld(); - if (craftWorld == null) { - return null; - } - return net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(craftWorld.getHandle(), new BlockPos(spawnLocation.getBlockX(), - spawnLocation.getBlockY(), spawnLocation.getBlockZ()), 0, true, false) - .map(vec3D -> new Location(spawnLocation.getWorld(), vec3D.x(), vec3D.y(), vec3D.z())) - .orElse(null); - } - - private static ListTag doubleList(final double... values) { - final ListTag tagList = new ListTag(); - for (final double d : values) { - tagList.add(DoubleTag.valueOf(d)); - } - return tagList; - } - -} diff --git a/hyperverse-nms-1-21-3/build.gradle.kts b/hyperverse-nms-1-21-3/build.gradle.kts deleted file mode 100644 index 19a0053e..00000000 --- a/hyperverse-nms-1-21-3/build.gradle.kts +++ /dev/null @@ -1,22 +0,0 @@ -plugins { - id("hyperverse.base-conventions") - alias(libs.plugins.paperweight.userdev) -} - -indra { - javaVersions { - minimumToolchain(21) - target(21) - } -} - -dependencies { - paperweight.paperDevBundle("1.21.3-R0.1-SNAPSHOT") - compileOnly(projects.hyperverseNmsCommon) -} - -tasks { - assemble { - dependsOn(reobfJar) - } -} diff --git a/hyperverse-nms-1-21-3/src/main/java/org/incendo/hyperverse/platform/v1_21_3/NMSImpl.java b/hyperverse-nms-1-21-3/src/main/java/org/incendo/hyperverse/platform/v1_21_3/NMSImpl.java deleted file mode 100644 index 792be08f..00000000 --- a/hyperverse-nms-1-21-3/src/main/java/org/incendo/hyperverse/platform/v1_21_3/NMSImpl.java +++ /dev/null @@ -1,255 +0,0 @@ -// -// Hyperverse - A minecraft world management plugin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -package org.incendo.hyperverse.platform.v1_21_3; - -import co.aikar.taskchain.TaskChainFactory; -import com.google.inject.Inject; -import io.papermc.lib.PaperLib; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; -import java.util.Optional; - -import net.minecraft.BlockUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.border.WorldBorder; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.entity.EntityLookup; -import net.minecraft.world.level.entity.PersistentEntitySectionManager; -import net.minecraft.world.level.portal.PortalForcer; -import net.minecraft.world.phys.Vec3; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.Logger; -import org.apache.logging.log4j.core.filter.RegexFilter; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.incendo.hyperverse.util.HyperConfigShouldGroupProfiles; -import org.incendo.hyperverse.util.NMS; - -@SuppressWarnings("unused") -public class NMSImpl implements NMS { - - private final TaskChainFactory taskFactory; - private Field entitySectionManager; - private Field entityLookup; - private org.apache.logging.log4j.core.Logger worldServerLogger; - - @Inject public NMSImpl(final TaskChainFactory taskFactory, final @HyperConfigShouldGroupProfiles boolean hyperConfiguration) { - this.taskFactory = taskFactory; - if (hyperConfiguration) { - try { - final Field field = ServerLevel.class.getDeclaredField("LOGGER"); - field.setAccessible(true); - this.worldServerLogger = (Logger) field.get(null); - } catch (final Exception e) { - e.printStackTrace(); - } - try { - final RegexFilter regexFilter = RegexFilter - .createFilter("[\\S\\s]*Force-added player with duplicate UUID[\\S\\s]*", null, false, - Filter.Result.DENY, Filter.Result.ACCEPT); - this.worldServerLogger.addFilter(regexFilter); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - - @Override @Nullable public Location getOrCreateNetherPortal(@NotNull final org.bukkit.entity.Entity entity, - @NotNull final Location origin) { - final ServerLevel worldServer = Objects.requireNonNull(((CraftWorld) origin.getWorld()).getHandle()); - final PortalForcer portalTravelAgent = Objects.requireNonNull(worldServer.getPortalForcer()); - final Entity nmsEntity = Objects.requireNonNull(((CraftEntity) entity).getHandle()); - final BlockPos blockPosition = new BlockPos(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); - final WorldBorder worldBorder = worldServer.getWorldBorder(); - Optional existingPortalPosition = Objects.requireNonNull(portalTravelAgent, "travel agent") - .findClosestPortalPosition(Objects.requireNonNull(blockPosition, "position"), worldBorder,128); - if (existingPortalPosition.isPresent()) { - BlockPos bottomLeft = existingPortalPosition.get(); - return new Location(origin.getWorld(), bottomLeft.getX(), bottomLeft.getY(), bottomLeft.getZ()); - } - Optional createdPortal = portalTravelAgent.createPortal(blockPosition, - nmsEntity.getDirection().getAxis(), nmsEntity, - 16); - if (createdPortal.isEmpty()) { - return null; - } - final BlockUtil.FoundRectangle rectangle = createdPortal.get(); - return new Location(origin.getWorld(), rectangle.minCorner.getX() + 1D, rectangle.minCorner.getY() - 1D, - rectangle.minCorner.getZ() + 1D); - } - - @Override @Nullable public Location getDimensionSpawn(@NotNull final Location origin) { - if (Objects.requireNonNull(origin.getWorld()).getEnvironment() - == World.Environment.THE_END) { - return new Location(origin.getWorld(), 100, 50, 0); - } - return origin.getWorld().getSpawnLocation(); - } - - @Override public void writePlayerData(@NotNull final Player player, @NotNull final Path file) { - final CompoundTag playerTag = new CompoundTag(); - final net.minecraft.world.entity.player.Player entityPlayer = ((CraftPlayer) player).getHandle(); - entityPlayer.save(playerTag); - - if (!playerTag.contains("hyperverse")) { - playerTag.put("hyperverse", new CompoundTag()); - } - final CompoundTag hyperverse = playerTag.getCompound("hyperverse"); - hyperverse.putLong("writeTime", System.currentTimeMillis()); - hyperverse.putString("version", Bukkit.getPluginManager().getPlugin("Hyperverse").getDescription().getVersion()); - - taskFactory.newChain().async(() -> { - try (final OutputStream outputStream = Files.newOutputStream(file)) { - NbtIo.writeCompressed(playerTag, outputStream); - } catch (final Exception e) { - e.printStackTrace(); - } - }).execute(); - } - - @Override public void readPlayerData(@NotNull final Player player, @NotNull final Path file, @NotNull final Runnable whenDone) { - final Location originLocation = player.getLocation().clone(); - taskFactory.newChain().asyncFirst(() -> { - try (final InputStream inputStream = Files.newInputStream(file)) { - return Optional.of(NbtIo.readCompressed(inputStream, NbtAccounter.unlimitedHeap())); - } catch (final Exception e) { - e.printStackTrace(); - } - return Optional.empty(); - }).syncLast((optionalCompound) -> { - if (!optionalCompound.isPresent()) { - return; - } - final CompoundTag compound = (CompoundTag) optionalCompound.get(); - PaperLib.getChunkAtAsync(originLocation).thenAccept(chunk -> { - // Health and hunger don't update properly, so we - // give them a little help - final float health = compound.getFloat("Health"); - final int foodLevel = compound.getInt("foodLevel"); - - // Restore bed spawn - final String spawnWorld = compound.getString("SpawnWorld"); - final int spawnX = compound.getInt("SpawnX"); - final int spawnY = compound.getInt("SpawnY"); - final int spawnZ = compound.getInt("SpawnZ"); - final Location spawnLocation = new Location(Bukkit.getWorld(spawnWorld), spawnX, - spawnY, spawnZ); - - final ServerPlayer entityPlayer = ((CraftPlayer) player).getHandle(); - - // We re-write the extra Bukkit data as to not - // mess up the profile - ((CraftPlayer) player).setExtraData(compound); - // Set the position to the player's current position - Vec3 pos = entityPlayer.position(); - compound.put("Pos", doubleList(pos.x, pos.y, pos.z)); - // Set the world to the player's current world - compound.putString("world", player.getWorld().getName()); - // Store persistent values - ((CraftPlayer) player).storeBukkitValues(compound); - - // We start by doing a total reset - entityPlayer.reset(); - entityPlayer.load(compound); - - entityPlayer.effectsDirty = true; - entityPlayer.onUpdateAbilities(); - player.teleport(originLocation); - - final ServerLevel worldServer = ((CraftWorld) originLocation.getWorld()).getHandle(); - final DimensionType dimensionManager = worldServer.dimensionType(); - - // Prevent annoying message - // Spigot-obf = decouple() - entityPlayer.unRide(); - worldServer.removePlayerImmediately(entityPlayer, Entity.RemovalReason.CHANGED_DIMENSION); - // worldServer.removePlayer above should remove the player from the - // map, but that doesn't always happen. This is a last effort - // attempt to prevent the annoying "Force re-added" message - // from appearing - try { - if (this.entitySectionManager == null) { - this.entitySectionManager = worldServer.getClass().getDeclaredField("entityManager"); - this.entitySectionManager.setAccessible(true); - } - final PersistentEntitySectionManager esm = (PersistentEntitySectionManager) this.entitySectionManager.get(worldServer); - if (this.entityLookup == null) { - this.entityLookup = esm.getClass().getDeclaredField("visibleEntityStorage"); - } - final EntityLookup lookup = (EntityLookup) this.entityLookup.get(esm); - lookup.remove(entityPlayer); - } catch (final NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } - - // pre 1.18 code = PlayerList#moveToWorld - entityPlayer.server.getPlayerList().remove(entityPlayer); - worldServer.getServer().getPlayerList().respawn(entityPlayer, true, - Entity.RemovalReason.CHANGED_DIMENSION, PlayerRespawnEvent.RespawnReason.PLUGIN, originLocation); - - // Apply health and foodLevel - player.setHealth(health); - player.setFoodLevel(foodLevel); - player.setPortalCooldown(40); - player.setBedSpawnLocation(spawnLocation, true); - }); - }).execute(whenDone); - } - - @Override @Nullable public Location findBedRespawn(@NotNull final Location spawnLocation) { - final CraftWorld craftWorld = (CraftWorld) spawnLocation.getWorld(); - if (craftWorld == null) { - return null; - } - - return ServerPlayer.findRespawnAndUseSpawnBlock(craftWorld.getHandle(), new BlockPos(spawnLocation.getBlockX(), - spawnLocation.getBlockY(), spawnLocation.getBlockZ()), 0, true, false) - .map(ServerPlayer.RespawnPosAngle::position) - .map(pos -> new Location(spawnLocation.getWorld(), pos.x(), pos.y(), pos.z())) - .orElse(null); - } - - private static ListTag doubleList(final double... values) { - final ListTag tagList = new ListTag(); - for (final double d : values) { - tagList.add(DoubleTag.valueOf(d)); - } - return tagList; - } - -} diff --git a/hyperverse-nms-1-21-4/src/main/java/org/incendo/hyperverse/platform/v1_21_4/NMSImpl.java b/hyperverse-nms-1-21-4/src/main/java/org/incendo/hyperverse/platform/v1_21_4/NMSImpl.java deleted file mode 100644 index 9eccd954..00000000 --- a/hyperverse-nms-1-21-4/src/main/java/org/incendo/hyperverse/platform/v1_21_4/NMSImpl.java +++ /dev/null @@ -1,255 +0,0 @@ -// -// Hyperverse - A minecraft world management plugin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -package org.incendo.hyperverse.platform.v1_21_4; - -import co.aikar.taskchain.TaskChainFactory; -import com.google.inject.Inject; -import io.papermc.lib.PaperLib; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; -import java.util.Optional; - -import net.minecraft.BlockUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.border.WorldBorder; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.entity.EntityLookup; -import net.minecraft.world.level.entity.PersistentEntitySectionManager; -import net.minecraft.world.level.portal.PortalForcer; -import net.minecraft.world.phys.Vec3; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.Logger; -import org.apache.logging.log4j.core.filter.RegexFilter; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.incendo.hyperverse.util.HyperConfigShouldGroupProfiles; -import org.incendo.hyperverse.util.NMS; - -@SuppressWarnings("unused") -public class NMSImpl implements NMS { - - private final TaskChainFactory taskFactory; - private Field entitySectionManager; - private Field entityLookup; - private org.apache.logging.log4j.core.Logger worldServerLogger; - - @Inject public NMSImpl(final TaskChainFactory taskFactory, final @HyperConfigShouldGroupProfiles boolean hyperConfiguration) { - this.taskFactory = taskFactory; - if (hyperConfiguration) { - try { - final Field field = ServerLevel.class.getDeclaredField("LOGGER"); - field.setAccessible(true); - this.worldServerLogger = (Logger) field.get(null); - } catch (final Exception e) { - e.printStackTrace(); - } - try { - final RegexFilter regexFilter = RegexFilter - .createFilter("[\\S\\s]*Force-added player with duplicate UUID[\\S\\s]*", null, false, - Filter.Result.DENY, Filter.Result.ACCEPT); - this.worldServerLogger.addFilter(regexFilter); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - - @Override @Nullable public Location getOrCreateNetherPortal(@NotNull final org.bukkit.entity.Entity entity, - @NotNull final Location origin) { - final ServerLevel worldServer = Objects.requireNonNull(((CraftWorld) origin.getWorld()).getHandle()); - final PortalForcer portalTravelAgent = Objects.requireNonNull(worldServer.getPortalForcer()); - final Entity nmsEntity = Objects.requireNonNull(((CraftEntity) entity).getHandle()); - final BlockPos blockPosition = new BlockPos(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); - final WorldBorder worldBorder = worldServer.getWorldBorder(); - Optional existingPortalPosition = Objects.requireNonNull(portalTravelAgent, "travel agent") - .findClosestPortalPosition(Objects.requireNonNull(blockPosition, "position"), worldBorder,128); - if (existingPortalPosition.isPresent()) { - BlockPos bottomLeft = existingPortalPosition.get(); - return new Location(origin.getWorld(), bottomLeft.getX(), bottomLeft.getY(), bottomLeft.getZ()); - } - Optional createdPortal = portalTravelAgent.createPortal(blockPosition, - nmsEntity.getDirection().getAxis(), nmsEntity, - 16); - if (createdPortal.isEmpty()) { - return null; - } - final BlockUtil.FoundRectangle rectangle = createdPortal.get(); - return new Location(origin.getWorld(), rectangle.minCorner.getX() + 1D, rectangle.minCorner.getY() - 1D, - rectangle.minCorner.getZ() + 1D); - } - - @Override @Nullable public Location getDimensionSpawn(@NotNull final Location origin) { - if (Objects.requireNonNull(origin.getWorld()).getEnvironment() - == World.Environment.THE_END) { - return new Location(origin.getWorld(), 100, 50, 0); - } - return origin.getWorld().getSpawnLocation(); - } - - @Override public void writePlayerData(@NotNull final Player player, @NotNull final Path file) { - final CompoundTag playerTag = new CompoundTag(); - final net.minecraft.world.entity.player.Player entityPlayer = ((CraftPlayer) player).getHandle(); - entityPlayer.save(playerTag); - - if (!playerTag.contains("hyperverse")) { - playerTag.put("hyperverse", new CompoundTag()); - } - final CompoundTag hyperverse = playerTag.getCompound("hyperverse"); - hyperverse.putLong("writeTime", System.currentTimeMillis()); - hyperverse.putString("version", Bukkit.getPluginManager().getPlugin("Hyperverse").getDescription().getVersion()); - - taskFactory.newChain().async(() -> { - try (final OutputStream outputStream = Files.newOutputStream(file)) { - NbtIo.writeCompressed(playerTag, outputStream); - } catch (final Exception e) { - e.printStackTrace(); - } - }).execute(); - } - - @Override public void readPlayerData(@NotNull final Player player, @NotNull final Path file, @NotNull final Runnable whenDone) { - final Location originLocation = player.getLocation().clone(); - taskFactory.newChain().asyncFirst(() -> { - try (final InputStream inputStream = Files.newInputStream(file)) { - return Optional.of(NbtIo.readCompressed(inputStream, NbtAccounter.unlimitedHeap())); - } catch (final Exception e) { - e.printStackTrace(); - } - return Optional.empty(); - }).syncLast((optionalCompound) -> { - if (!optionalCompound.isPresent()) { - return; - } - final CompoundTag compound = (CompoundTag) optionalCompound.get(); - PaperLib.getChunkAtAsync(originLocation).thenAccept(chunk -> { - // Health and hunger don't update properly, so we - // give them a little help - final float health = compound.getFloat("Health"); - final int foodLevel = compound.getInt("foodLevel"); - - // Restore bed spawn - final String spawnWorld = compound.getString("SpawnWorld"); - final int spawnX = compound.getInt("SpawnX"); - final int spawnY = compound.getInt("SpawnY"); - final int spawnZ = compound.getInt("SpawnZ"); - final Location spawnLocation = new Location(Bukkit.getWorld(spawnWorld), spawnX, - spawnY, spawnZ); - - final ServerPlayer entityPlayer = ((CraftPlayer) player).getHandle(); - - // We re-write the extra Bukkit data as to not - // mess up the profile - ((CraftPlayer) player).setExtraData(compound); - // Set the position to the player's current position - Vec3 pos = entityPlayer.position(); - compound.put("Pos", doubleList(pos.x, pos.y, pos.z)); - // Set the world to the player's current world - compound.putString("world", player.getWorld().getName()); - // Store persistent values - ((CraftPlayer) player).storeBukkitValues(compound); - - // We start by doing a total reset - entityPlayer.reset(); - entityPlayer.load(compound); - - entityPlayer.effectsDirty = true; - entityPlayer.onUpdateAbilities(); - player.teleport(originLocation); - - final ServerLevel worldServer = ((CraftWorld) originLocation.getWorld()).getHandle(); - final DimensionType dimensionManager = worldServer.dimensionType(); - - // Prevent annoying message - // Spigot-obf = decouple() - entityPlayer.unRide(); - worldServer.removePlayerImmediately(entityPlayer, Entity.RemovalReason.CHANGED_DIMENSION); - // worldServer.removePlayer above should remove the player from the - // map, but that doesn't always happen. This is a last effort - // attempt to prevent the annoying "Force re-added" message - // from appearing - try { - if (this.entitySectionManager == null) { - this.entitySectionManager = worldServer.getClass().getDeclaredField("entityManager"); - this.entitySectionManager.setAccessible(true); - } - final PersistentEntitySectionManager esm = (PersistentEntitySectionManager) this.entitySectionManager.get(worldServer); - if (this.entityLookup == null) { - this.entityLookup = esm.getClass().getDeclaredField("visibleEntityStorage"); - } - final EntityLookup lookup = (EntityLookup) this.entityLookup.get(esm); - lookup.remove(entityPlayer); - } catch (final NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } - - // pre 1.18 code = PlayerList#moveToWorld - entityPlayer.server.getPlayerList().remove(entityPlayer); - worldServer.getServer().getPlayerList().respawn(entityPlayer, true, - Entity.RemovalReason.CHANGED_DIMENSION, PlayerRespawnEvent.RespawnReason.PLUGIN, originLocation); - - // Apply health and foodLevel - player.setHealth(health); - player.setFoodLevel(foodLevel); - player.setPortalCooldown(40); - player.setBedSpawnLocation(spawnLocation, true); - }); - }).execute(whenDone); - } - - @Override @Nullable public Location findBedRespawn(@NotNull final Location spawnLocation) { - final CraftWorld craftWorld = (CraftWorld) spawnLocation.getWorld(); - if (craftWorld == null) { - return null; - } - - return ServerPlayer.findRespawnAndUseSpawnBlock(craftWorld.getHandle(), new BlockPos(spawnLocation.getBlockX(), - spawnLocation.getBlockY(), spawnLocation.getBlockZ()), 0, true, false) - .map(ServerPlayer.RespawnPosAngle::position) - .map(pos -> new Location(spawnLocation.getWorld(), pos.x(), pos.y(), pos.z())) - .orElse(null); - } - - private static ListTag doubleList(final double... values) { - final ListTag tagList = new ListTag(); - for (final double d : values) { - tagList.add(DoubleTag.valueOf(d)); - } - return tagList; - } - -} diff --git a/hyperverse-nms-1-21-5/build.gradle.kts b/hyperverse-nms-1-21-5/build.gradle.kts deleted file mode 100644 index 1eb7e8ba..00000000 --- a/hyperverse-nms-1-21-5/build.gradle.kts +++ /dev/null @@ -1,22 +0,0 @@ -plugins { - id("hyperverse.base-conventions") - alias(libs.plugins.paperweight.userdev) -} - -indra { - javaVersions { - minimumToolchain(21) - target(21) - } -} - -dependencies { - paperweight.paperDevBundle("1.21.5-R0.1-SNAPSHOT") - compileOnly(projects.hyperverseNmsCommon) -} - -tasks { - assemble { - dependsOn(reobfJar) - } -} diff --git a/hyperverse-nms-1-21-5/src/main/java/org/incendo/hyperverse/platform/v1_21_5/NMSImpl.java b/hyperverse-nms-1-21-5/src/main/java/org/incendo/hyperverse/platform/v1_21_5/NMSImpl.java deleted file mode 100644 index 032010bf..00000000 --- a/hyperverse-nms-1-21-5/src/main/java/org/incendo/hyperverse/platform/v1_21_5/NMSImpl.java +++ /dev/null @@ -1,278 +0,0 @@ -// -// Hyperverse - A minecraft world management plugin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -package org.incendo.hyperverse.platform.v1_21_5; - -import co.aikar.taskchain.TaskChainFactory; -import com.google.inject.Inject; -import io.papermc.lib.PaperLib; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; -import java.util.Optional; - -import net.minecraft.BlockUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.IntTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NumericTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.border.WorldBorder; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.entity.EntityLookup; -import net.minecraft.world.level.entity.PersistentEntitySectionManager; -import net.minecraft.world.level.portal.PortalForcer; -import net.minecraft.world.phys.Vec3; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.Logger; -import org.apache.logging.log4j.core.filter.RegexFilter; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.incendo.hyperverse.util.HyperConfigShouldGroupProfiles; -import org.incendo.hyperverse.util.NMS; - -@SuppressWarnings("unused") -public class NMSImpl implements NMS { - - private final TaskChainFactory taskFactory; - private Field entitySectionManager; - private Field entityLookup; - private org.apache.logging.log4j.core.Logger worldServerLogger; - - @Inject public NMSImpl(final TaskChainFactory taskFactory, final @HyperConfigShouldGroupProfiles boolean hyperConfiguration) { - this.taskFactory = taskFactory; - if (hyperConfiguration) { - try { - final Field field = ServerLevel.class.getDeclaredField("LOGGER"); - field.setAccessible(true); - this.worldServerLogger = (Logger) field.get(null); - } catch (final Exception e) { - e.printStackTrace(); - } - try { - final RegexFilter regexFilter = RegexFilter - .createFilter("[\\S\\s]*Force-added player with duplicate UUID[\\S\\s]*", null, false, - Filter.Result.DENY, Filter.Result.ACCEPT); - this.worldServerLogger.addFilter(regexFilter); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - - @Override @Nullable public Location getOrCreateNetherPortal(@NotNull final org.bukkit.entity.Entity entity, - @NotNull final Location origin) { - final ServerLevel worldServer = Objects.requireNonNull(((CraftWorld) origin.getWorld()).getHandle()); - final PortalForcer portalTravelAgent = Objects.requireNonNull(worldServer.getPortalForcer()); - final Entity nmsEntity = Objects.requireNonNull(((CraftEntity) entity).getHandle()); - final BlockPos blockPosition = new BlockPos(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); - final WorldBorder worldBorder = worldServer.getWorldBorder(); - Optional existingPortalPosition = Objects.requireNonNull(portalTravelAgent, "travel agent") - .findClosestPortalPosition(Objects.requireNonNull(blockPosition, "position"), worldBorder,128); - if (existingPortalPosition.isPresent()) { - BlockPos bottomLeft = existingPortalPosition.get(); - return new Location(origin.getWorld(), bottomLeft.getX(), bottomLeft.getY(), bottomLeft.getZ()); - } - Optional createdPortal = portalTravelAgent.createPortal(blockPosition, - nmsEntity.getDirection().getAxis(), nmsEntity, - 16); - if (createdPortal.isEmpty()) { - return null; - } - final BlockUtil.FoundRectangle rectangle = createdPortal.get(); - return new Location(origin.getWorld(), rectangle.minCorner.getX() + 1D, rectangle.minCorner.getY() - 1D, - rectangle.minCorner.getZ() + 1D); - } - - @Override @Nullable public Location getDimensionSpawn(@NotNull final Location origin) { - if (Objects.requireNonNull(origin.getWorld()).getEnvironment() - == World.Environment.THE_END) { - return new Location(origin.getWorld(), 100, 50, 0); - } - return origin.getWorld().getSpawnLocation(); - } - - @Override - public void writePlayerData(@NotNull final Player player, @NotNull final Path file) { - final CompoundTag playerTag = new CompoundTag(); - final net.minecraft.world.entity.player.Player entityPlayer = ((CraftPlayer) player).getHandle(); - entityPlayer.save(playerTag); - - // Handle the Optional return type of getCompound - CompoundTag hyperverse = playerTag.getCompound("hyperverse").orElse(new CompoundTag()); - // If "hyperverse" didn't exist, we need to add it to playerTag - playerTag.put("hyperverse", hyperverse); - - hyperverse.putLong("writeTime", System.currentTimeMillis()); - hyperverse.putString("version", Bukkit.getPluginManager().getPlugin("Hyperverse").getDescription().getVersion()); - - taskFactory.newChain().async(() -> { - try (final OutputStream outputStream = Files.newOutputStream(file)) { - NbtIo.writeCompressed(playerTag, outputStream); - } catch (final Exception e) { - e.printStackTrace(); - } - }).execute(); - } - - @Override - public void readPlayerData(@NotNull final Player player, @NotNull final Path file, @NotNull final Runnable whenDone) { - final Location originLocation = player.getLocation().clone(); - taskFactory.newChain().asyncFirst(() -> { - try (final InputStream inputStream = Files.newInputStream(file)) { - return Optional.of(NbtIo.readCompressed(inputStream, NbtAccounter.unlimitedHeap())); - } catch (final Exception e) { - e.printStackTrace(); - } - return Optional.empty(); - }).syncLast((optionalCompound) -> { - if (!optionalCompound.isPresent()) { - return; - } - final CompoundTag compound = (CompoundTag) optionalCompound.get(); - PaperLib.getChunkAtAsync(originLocation).thenAccept(chunk -> { - // Health and hunger don't update properly, so we give them a little help - final float health = compound.getFloat("Health").orElse(20.0f); // Default to 20 (full health) - final int foodLevel = compound.getInt("foodLevel").orElse(20); // Default to 20 (full food) - - // Restore bed spawn - final String spawnWorld = compound.getString("SpawnWorld").orElse(player.getWorld().getName()); // Default to current world - final int spawnX = compound.getInt("SpawnX").orElse((int) originLocation.getX()); - final int spawnY = compound.getInt("SpawnY").orElse((int) originLocation.getY()); - final int spawnZ = compound.getInt("SpawnZ").orElse((int) originLocation.getZ()); - final Location spawnLocation = new Location(Bukkit.getWorld(spawnWorld), spawnX, spawnY, spawnZ); - - final ServerPlayer entityPlayer = ((CraftPlayer) player).getHandle(); - - // We re-write the extra Bukkit data as to not mess up the profile - ((CraftPlayer) player).setExtraData(compound); - // Set the position to the player's current position - Vec3 pos = entityPlayer.position(); - compound.put("Pos", doubleList(pos.x, pos.y, pos.z)); - // Set the world to the player's current world - compound.putString("world", player.getWorld().getName()); - // Store persistent values - ((CraftPlayer) player).storeBukkitValues(compound); - - // We start by doing a total reset - entityPlayer.reset(); - entityPlayer.load(compound); - - entityPlayer.effectsDirty = true; - entityPlayer.onUpdateAbilities(); - player.teleport(originLocation); - - final ServerLevel worldServer = ((CraftWorld) originLocation.getWorld()).getHandle(); - final DimensionType dimensionManager = worldServer.dimensionType(); - - // Prevent annoying message - // Spigot-obf = decouple() - entityPlayer.unRide(); - worldServer.removePlayerImmediately(entityPlayer, Entity.RemovalReason.CHANGED_DIMENSION); - // worldServer.removePlayer above should remove the player from the map, but that doesn't always happen - try { - if (this.entitySectionManager == null) { - this.entitySectionManager = worldServer.getClass().getDeclaredField("entityManager"); - this.entitySectionManager.setAccessible(true); - } - final PersistentEntitySectionManager esm = (PersistentEntitySectionManager) this.entitySectionManager.get(worldServer); - if (this.entityLookup == null) { - this.entityLookup = esm.getClass().getDeclaredField("visibleEntityStorage"); - } - final EntityLookup lookup = (EntityLookup) this.entityLookup.get(esm); - lookup.remove(entityPlayer); - } catch (final NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } - - // pre 1.18 code = PlayerList#moveToWorld - entityPlayer.server.getPlayerList().remove(entityPlayer); - worldServer.getServer().getPlayerList().respawn(entityPlayer, true, - Entity.RemovalReason.CHANGED_DIMENSION, PlayerRespawnEvent.RespawnReason.PLUGIN, originLocation); - - // Apply health and foodLevel - player.setHealth(health); - player.setFoodLevel(foodLevel); - player.setPortalCooldown(40); - player.setBedSpawnLocation(spawnLocation, true); - }); - }).execute(whenDone); - } - - @Override - @Nullable - public Location findBedRespawn(@NotNull final Location spawnLocation) { - final CraftWorld craftWorld = (CraftWorld) spawnLocation.getWorld(); - if (craftWorld == null) { - return null; - } - - // Create a BlockPos for the spawn location - BlockPos blockPos = new BlockPos(spawnLocation.getBlockX(), spawnLocation.getBlockY(), spawnLocation.getBlockZ()); - - // Get the dimension ResourceKey from the ServerLevel - ServerLevel serverLevel = craftWorld.getHandle(); - ResourceKey dimension = serverLevel.dimension(); - - // Create a RespawnConfig instance with the required arguments - ServerPlayer.RespawnConfig respawnConfig = new ServerPlayer.RespawnConfig( - dimension, // The dimension of the world - blockPos, // The position to check for respawn - 0.0f, // Yaw (rotation angle), default to 0 - true // Forced flag, set to true to match previous behavior - ); - - // Call the method with the correct arguments - return ServerPlayer.findRespawnAndUseSpawnBlock( - serverLevel, - respawnConfig, - false // Assuming the boolean is respawnAfterDeath - ) - .map(ServerPlayer.RespawnPosAngle::position) - .map(pos -> new Location(spawnLocation.getWorld(), pos.x(), pos.y(), pos.z())) - .orElse(null); - } - - private static ListTag doubleList(final double... values) { - final ListTag tagList = new ListTag(); - for (final double d : values) { - tagList.add(DoubleTag.valueOf(d)); - } - return tagList; - } - -} diff --git a/hyperverse-nms-1-21-6/build.gradle.kts b/hyperverse-nms-1-21-6/build.gradle.kts deleted file mode 100644 index 4e0c55ce..00000000 --- a/hyperverse-nms-1-21-6/build.gradle.kts +++ /dev/null @@ -1,22 +0,0 @@ -plugins { - id("hyperverse.base-conventions") - alias(libs.plugins.paperweight.userdev) -} - -indra { - javaVersions { - minimumToolchain(21) - target(21) - } -} - -dependencies { - paperweight.paperDevBundle("1.21.6-R0.1-SNAPSHOT") - compileOnly(projects.hyperverseNmsCommon) -} - -tasks { - assemble { - dependsOn(reobfJar) - } -} diff --git a/hyperverse-nms-1-21-7/build.gradle.kts b/hyperverse-nms-1-21-7/build.gradle.kts deleted file mode 100644 index 3f83cf6d..00000000 --- a/hyperverse-nms-1-21-7/build.gradle.kts +++ /dev/null @@ -1,22 +0,0 @@ -plugins { - id("hyperverse.base-conventions") - alias(libs.plugins.paperweight.userdev) -} - -indra { - javaVersions { - minimumToolchain(21) - target(21) - } -} - -dependencies { - paperweight.paperDevBundle("1.21.7-R0.1-SNAPSHOT") - compileOnly(projects.hyperverseNmsCommon) -} - -tasks { - assemble { - dependsOn(reobfJar) - } -} diff --git a/hyperverse-nms-1-21/build.gradle.kts b/hyperverse-nms-1-21/build.gradle.kts deleted file mode 100644 index 80cb781e..00000000 --- a/hyperverse-nms-1-21/build.gradle.kts +++ /dev/null @@ -1,22 +0,0 @@ -plugins { - id("hyperverse.base-conventions") - alias(libs.plugins.paperweight.userdev) -} - -indra { - javaVersions { - minimumToolchain(21) - target(21) - } -} - -dependencies { - paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") - compileOnly(projects.hyperverseNmsCommon) -} - -tasks { - assemble { - dependsOn(reobfJar) - } -} diff --git a/hyperverse-nms-1-21/src/main/java/org/incendo/hyperverse/platform/v1_21/NMSImpl.java b/hyperverse-nms-1-21/src/main/java/org/incendo/hyperverse/platform/v1_21/NMSImpl.java deleted file mode 100644 index ea5f6e46..00000000 --- a/hyperverse-nms-1-21/src/main/java/org/incendo/hyperverse/platform/v1_21/NMSImpl.java +++ /dev/null @@ -1,255 +0,0 @@ -// -// Hyperverse - A minecraft world management plugin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -package org.incendo.hyperverse.platform.v1_21; - -import co.aikar.taskchain.TaskChainFactory; -import com.google.inject.Inject; -import io.papermc.lib.PaperLib; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; -import java.util.Optional; - -import net.minecraft.BlockUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.border.WorldBorder; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.entity.EntityLookup; -import net.minecraft.world.level.entity.PersistentEntitySectionManager; -import net.minecraft.world.level.portal.PortalForcer; -import net.minecraft.world.phys.Vec3; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.Logger; -import org.apache.logging.log4j.core.filter.RegexFilter; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerRespawnEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.incendo.hyperverse.util.HyperConfigShouldGroupProfiles; -import org.incendo.hyperverse.util.NMS; - -@SuppressWarnings("unused") -public class NMSImpl implements NMS { - - private final TaskChainFactory taskFactory; - private Field entitySectionManager; - private Field entityLookup; - private org.apache.logging.log4j.core.Logger worldServerLogger; - - @Inject public NMSImpl(final TaskChainFactory taskFactory, final @HyperConfigShouldGroupProfiles boolean hyperConfiguration) { - this.taskFactory = taskFactory; - if (hyperConfiguration) { - try { - final Field field = ServerLevel.class.getDeclaredField("LOGGER"); - field.setAccessible(true); - this.worldServerLogger = (Logger) field.get(null); - } catch (final Exception e) { - e.printStackTrace(); - } - try { - final RegexFilter regexFilter = RegexFilter - .createFilter("[\\S\\s]*Force-added player with duplicate UUID[\\S\\s]*", null, false, - Filter.Result.DENY, Filter.Result.ACCEPT); - this.worldServerLogger.addFilter(regexFilter); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - - @Override @Nullable public Location getOrCreateNetherPortal(@NotNull final org.bukkit.entity.Entity entity, - @NotNull final Location origin) { - final ServerLevel worldServer = Objects.requireNonNull(((CraftWorld) origin.getWorld()).getHandle()); - final PortalForcer portalTravelAgent = Objects.requireNonNull(worldServer.getPortalForcer()); - final Entity nmsEntity = Objects.requireNonNull(((CraftEntity) entity).getHandle()); - final BlockPos blockPosition = new BlockPos(origin.getBlockX(), origin.getBlockY(), origin.getBlockZ()); - final WorldBorder worldBorder = worldServer.getWorldBorder(); - Optional existingPortalPosition = Objects.requireNonNull(portalTravelAgent, "travel agent") - .findClosestPortalPosition(Objects.requireNonNull(blockPosition, "position"), worldBorder,128); - if (existingPortalPosition.isPresent()) { - BlockPos bottomLeft = existingPortalPosition.get(); - return new Location(origin.getWorld(), bottomLeft.getX(), bottomLeft.getY(), bottomLeft.getZ()); - } - Optional createdPortal = portalTravelAgent.createPortal(blockPosition, - nmsEntity.getDirection().getAxis(), nmsEntity, - 16); - if (createdPortal.isEmpty()) { - return null; - } - final BlockUtil.FoundRectangle rectangle = createdPortal.get(); - return new Location(origin.getWorld(), rectangle.minCorner.getX() + 1D, rectangle.minCorner.getY() - 1D, - rectangle.minCorner.getZ() + 1D); - } - - @Override @Nullable public Location getDimensionSpawn(@NotNull final Location origin) { - if (Objects.requireNonNull(origin.getWorld()).getEnvironment() - == World.Environment.THE_END) { - return new Location(origin.getWorld(), 100, 50, 0); - } - return origin.getWorld().getSpawnLocation(); - } - - @Override public void writePlayerData(@NotNull final Player player, @NotNull final Path file) { - final CompoundTag playerTag = new CompoundTag(); - final net.minecraft.world.entity.player.Player entityPlayer = ((CraftPlayer) player).getHandle(); - entityPlayer.save(playerTag); - - if (!playerTag.contains("hyperverse")) { - playerTag.put("hyperverse", new CompoundTag()); - } - final CompoundTag hyperverse = playerTag.getCompound("hyperverse"); - hyperverse.putLong("writeTime", System.currentTimeMillis()); - hyperverse.putString("version", Bukkit.getPluginManager().getPlugin("Hyperverse").getDescription().getVersion()); - - taskFactory.newChain().async(() -> { - try (final OutputStream outputStream = Files.newOutputStream(file)) { - NbtIo.writeCompressed(playerTag, outputStream); - } catch (final Exception e) { - e.printStackTrace(); - } - }).execute(); - } - - @Override public void readPlayerData(@NotNull final Player player, @NotNull final Path file, @NotNull final Runnable whenDone) { - final Location originLocation = player.getLocation().clone(); - taskFactory.newChain().asyncFirst(() -> { - try (final InputStream inputStream = Files.newInputStream(file)) { - return Optional.of(NbtIo.readCompressed(inputStream, NbtAccounter.unlimitedHeap())); - } catch (final Exception e) { - e.printStackTrace(); - } - return Optional.empty(); - }).syncLast((optionalCompound) -> { - if (!optionalCompound.isPresent()) { - return; - } - final CompoundTag compound = (CompoundTag) optionalCompound.get(); - PaperLib.getChunkAtAsync(originLocation).thenAccept(chunk -> { - // Health and hunger don't update properly, so we - // give them a little help - final float health = compound.getFloat("Health"); - final int foodLevel = compound.getInt("foodLevel"); - - // Restore bed spawn - final String spawnWorld = compound.getString("SpawnWorld"); - final int spawnX = compound.getInt("SpawnX"); - final int spawnY = compound.getInt("SpawnY"); - final int spawnZ = compound.getInt("SpawnZ"); - final Location spawnLocation = new Location(Bukkit.getWorld(spawnWorld), spawnX, - spawnY, spawnZ); - - final ServerPlayer entityPlayer = ((CraftPlayer) player).getHandle(); - - // We re-write the extra Bukkit data as to not - // mess up the profile - ((CraftPlayer) player).setExtraData(compound); - // Set the position to the player's current position - Vec3 pos = entityPlayer.position(); - compound.put("Pos", doubleList(pos.x, pos.y, pos.z)); - // Set the world to the player's current world - compound.putString("world", player.getWorld().getName()); - // Store persistent values - ((CraftPlayer) player).storeBukkitValues(compound); - - // We start by doing a total reset - entityPlayer.reset(); - entityPlayer.load(compound); - - entityPlayer.effectsDirty = true; - entityPlayer.onUpdateAbilities(); - player.teleport(originLocation); - - final ServerLevel worldServer = ((CraftWorld) originLocation.getWorld()).getHandle(); - final DimensionType dimensionManager = worldServer.dimensionType(); - - // Prevent annoying message - // Spigot-obf = decouple() - entityPlayer.unRide(); - worldServer.removePlayerImmediately(entityPlayer, Entity.RemovalReason.CHANGED_DIMENSION); - // worldServer.removePlayer above should remove the player from the - // map, but that doesn't always happen. This is a last effort - // attempt to prevent the annoying "Force re-added" message - // from appearing - try { - if (this.entitySectionManager == null) { - this.entitySectionManager = worldServer.getClass().getDeclaredField("entityManager"); - this.entitySectionManager.setAccessible(true); - } - final PersistentEntitySectionManager esm = (PersistentEntitySectionManager) this.entitySectionManager.get(worldServer); - if (this.entityLookup == null) { - this.entityLookup = esm.getClass().getDeclaredField("visibleEntityStorage"); - } - final EntityLookup lookup = (EntityLookup) this.entityLookup.get(esm); - lookup.remove(entityPlayer); - } catch (final NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } - - // pre 1.18 code = PlayerList#moveToWorld - entityPlayer.server.getPlayerList().remove(entityPlayer); - worldServer.getServer().getPlayerList().respawn(entityPlayer, true, - Entity.RemovalReason.CHANGED_DIMENSION, PlayerRespawnEvent.RespawnReason.PLUGIN, originLocation); - - // Apply health and foodLevel - player.setHealth(health); - player.setFoodLevel(foodLevel); - player.setPortalCooldown(40); - player.setBedSpawnLocation(spawnLocation, true); - }); - }).execute(whenDone); - } - - @Override @Nullable public Location findBedRespawn(@NotNull final Location spawnLocation) { - final CraftWorld craftWorld = (CraftWorld) spawnLocation.getWorld(); - if (craftWorld == null) { - return null; - } - - return ServerPlayer.findRespawnAndUseSpawnBlock(craftWorld.getHandle(), new BlockPos(spawnLocation.getBlockX(), - spawnLocation.getBlockY(), spawnLocation.getBlockZ()), 0, true, false) - .map(ServerPlayer.RespawnPosAngle::position) - .map(pos -> new Location(spawnLocation.getWorld(), pos.x(), pos.y(), pos.z())) - .orElse(null); - } - - private static ListTag doubleList(final double... values) { - final ListTag tagList = new ListTag(); - for (final double d : values) { - tagList.add(DoubleTag.valueOf(d)); - } - return tagList; - } - -} diff --git a/hyperverse-nms-1-20-6/build.gradle.kts b/hyperverse-nms-26-1/build.gradle.kts similarity index 54% rename from hyperverse-nms-1-20-6/build.gradle.kts rename to hyperverse-nms-26-1/build.gradle.kts index 1e721881..dbeb8494 100644 --- a/hyperverse-nms-1-20-6/build.gradle.kts +++ b/hyperverse-nms-26-1/build.gradle.kts @@ -5,18 +5,12 @@ plugins { indra { javaVersions { - minimumToolchain(21) - target(21) + minimumToolchain(25) + target(25) } } dependencies { - paperweight.paperDevBundle("1.20.6-R0.1-SNAPSHOT") + paperweight.paperDevBundle("26.1.2.build.+") compileOnly(projects.hyperverseNmsCommon) } - -tasks { - assemble { - dependsOn(reobfJar) - } -} diff --git a/hyperverse-nms-1-21-7/src/main/java/org/incendo/hyperverse/platform/v1_21_7/NMSImpl.java b/hyperverse-nms-26-1/src/main/java/org/incendo/hyperverse/platform/v26_1_2/NMSImpl.java similarity index 96% rename from hyperverse-nms-1-21-7/src/main/java/org/incendo/hyperverse/platform/v1_21_7/NMSImpl.java rename to hyperverse-nms-26-1/src/main/java/org/incendo/hyperverse/platform/v26_1_2/NMSImpl.java index 41f0a9e4..233178f2 100644 --- a/hyperverse-nms-1-21-7/src/main/java/org/incendo/hyperverse/platform/v1_21_7/NMSImpl.java +++ b/hyperverse-nms-26-1/src/main/java/org/incendo/hyperverse/platform/v26_1_2/NMSImpl.java @@ -15,7 +15,7 @@ // along with this program. If not, see . // -package org.incendo.hyperverse.platform.v1_21_7; +package org.incendo.hyperverse.platform.v26_1_2; import co.aikar.taskchain.TaskChainFactory; import com.google.inject.Inject; @@ -28,19 +28,16 @@ import java.util.Objects; import java.util.Optional; -import net.minecraft.BlockUtil; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.IntTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NumericTag; -import net.minecraft.nbt.StringTag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.BlockUtil; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import net.minecraft.world.level.border.WorldBorder; @@ -48,6 +45,7 @@ import net.minecraft.world.level.entity.EntityLookup; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.portal.PortalForcer; +import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.TagValueInput; import net.minecraft.world.level.storage.TagValueOutput; import net.minecraft.world.phys.Vec3; @@ -222,9 +220,9 @@ public void readPlayerData(@NotNull final Player player, @NotNull final Path fil } // pre 1.18 code = PlayerList#moveToWorld - entityPlayer.getServer().getPlayerList().remove(entityPlayer); + worldServer.getServer().getPlayerList().remove(entityPlayer); worldServer.getServer().getPlayerList().respawn(entityPlayer, true, - Entity.RemovalReason.CHANGED_DIMENSION, PlayerRespawnEvent.RespawnReason.PLUGIN, originLocation); + Entity.RemovalReason.CHANGED_DIMENSION, PlayerRespawnEvent.RespawnReason.PLUGIN); // Apply health and foodLevel player.setHealth(health); @@ -250,11 +248,16 @@ public Location findBedRespawn(@NotNull final Location spawnLocation) { ServerLevel serverLevel = craftWorld.getHandle(); ResourceKey dimension = serverLevel.dimension(); + LevelData.RespawnData respawnData = LevelData.RespawnData.of( + dimension, + blockPos, + 0.0f, + 0 + ); + // Create a RespawnConfig instance with the required arguments ServerPlayer.RespawnConfig respawnConfig = new ServerPlayer.RespawnConfig( - dimension, // The dimension of the world - blockPos, // The position to check for respawn - 0.0f, // Yaw (rotation angle), default to 0 + respawnData, // Yaw (rotation angle), default to 0 true // Forced flag, set to true to match previous behavior ); diff --git a/hyperverse-nms-1-21-4/build.gradle.kts b/hyperverse-nms-26-2/build.gradle.kts similarity index 54% rename from hyperverse-nms-1-21-4/build.gradle.kts rename to hyperverse-nms-26-2/build.gradle.kts index 5e67c30e..b88e23bb 100644 --- a/hyperverse-nms-1-21-4/build.gradle.kts +++ b/hyperverse-nms-26-2/build.gradle.kts @@ -5,18 +5,12 @@ plugins { indra { javaVersions { - minimumToolchain(21) - target(21) + minimumToolchain(25) + target(25) } } dependencies { - paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT") + paperweight.paperDevBundle("26.2.build.+") compileOnly(projects.hyperverseNmsCommon) } - -tasks { - assemble { - dependsOn(reobfJar) - } -} diff --git a/hyperverse-nms-1-21-6/src/main/java/org/incendo/hyperverse/platform/v1_21_6/NMSImpl.java b/hyperverse-nms-26-2/src/main/java/org.incendo.hyperverse.platform.v26_2/NMSImpl.java similarity index 96% rename from hyperverse-nms-1-21-6/src/main/java/org/incendo/hyperverse/platform/v1_21_6/NMSImpl.java rename to hyperverse-nms-26-2/src/main/java/org.incendo.hyperverse.platform.v26_2/NMSImpl.java index 88a05136..693129f2 100644 --- a/hyperverse-nms-1-21-6/src/main/java/org/incendo/hyperverse/platform/v1_21_6/NMSImpl.java +++ b/hyperverse-nms-26-2/src/main/java/org.incendo.hyperverse.platform.v26_2/NMSImpl.java @@ -15,7 +15,7 @@ // along with this program. If not, see . // -package org.incendo.hyperverse.platform.v1_21_6; +package org.incendo.hyperverse.platform.v26_2; import co.aikar.taskchain.TaskChainFactory; import com.google.inject.Inject; @@ -28,19 +28,16 @@ import java.util.Objects; import java.util.Optional; -import net.minecraft.BlockUtil; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.DoubleTag; -import net.minecraft.nbt.IntTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtAccounter; import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NumericTag; -import net.minecraft.nbt.StringTag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.BlockUtil; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import net.minecraft.world.level.border.WorldBorder; @@ -48,6 +45,7 @@ import net.minecraft.world.level.entity.EntityLookup; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.portal.PortalForcer; +import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.TagValueInput; import net.minecraft.world.level.storage.TagValueOutput; import net.minecraft.world.phys.Vec3; @@ -222,9 +220,9 @@ public void readPlayerData(@NotNull final Player player, @NotNull final Path fil } // pre 1.18 code = PlayerList#moveToWorld - entityPlayer.getServer().getPlayerList().remove(entityPlayer); + worldServer.getServer().getPlayerList().remove(entityPlayer); worldServer.getServer().getPlayerList().respawn(entityPlayer, true, - Entity.RemovalReason.CHANGED_DIMENSION, PlayerRespawnEvent.RespawnReason.PLUGIN, originLocation); + Entity.RemovalReason.CHANGED_DIMENSION, PlayerRespawnEvent.RespawnReason.PLUGIN); // Apply health and foodLevel player.setHealth(health); @@ -250,11 +248,16 @@ public Location findBedRespawn(@NotNull final Location spawnLocation) { ServerLevel serverLevel = craftWorld.getHandle(); ResourceKey dimension = serverLevel.dimension(); + LevelData.RespawnData respawnData = LevelData.RespawnData.of( + dimension, + blockPos, + 0.0f, + 0 + ); + // Create a RespawnConfig instance with the required arguments ServerPlayer.RespawnConfig respawnConfig = new ServerPlayer.RespawnConfig( - dimension, // The dimension of the world - blockPos, // The position to check for respawn - 0.0f, // Yaw (rotation angle), default to 0 + respawnData, // Yaw (rotation angle), default to 0 true // Forced flag, set to true to match previous behavior ); diff --git a/settings.gradle.kts b/settings.gradle.kts index 1b09a533..3b7334fd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,6 +3,7 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") pluginManagement { repositories { gradlePluginPortal() + maven("https://repo.papermc.io/repository/maven-public/") } includeBuild("gradle/build-logic") } @@ -13,10 +14,5 @@ include(":hyperverse-nms-common") include(":hyperverse-core") include(":hyperverse-nms-unsupported") -include(":hyperverse-nms-1-20-6") -include(":hyperverse-nms-1-21") -include(":hyperverse-nms-1-21-3") -include(":hyperverse-nms-1-21-4") -include(":hyperverse-nms-1-21-5") -include(":hyperverse-nms-1-21-6") -include(":hyperverse-nms-1-21-7") +include(":hyperverse-nms-26-1") +include(":hyperverse-nms-26-2")