diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 3c9f55afc3..8c40ee0284 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -18,7 +18,7 @@ repositories { } maven { name = "sponge" - url = uri("https://repo.spongepowered.org/maven") + url = uri("https://repo.spongepowered.org/repository/maven-public/") } maven { name = "EngineHub Repository" @@ -43,6 +43,7 @@ dependencies { implementation("net.ltgt.apt-idea:net.ltgt.apt-idea.gradle.plugin:0.21") implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.19.0") implementation("org.spongepowered:SpongeGradle:0.11.5") + implementation("org.spongepowered:vanillagradle:0.1") implementation("net.minecraftforge.gradle:ForgeGradle:4.0.9") implementation("net.fabricmc:fabric-loom:$loomVersion") implementation("net.fabricmc:sponge-mixin:$mixinVersion") diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index 5cea27b135..779506f9d2 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -29,18 +29,18 @@ configurations { } dependencies { - constraints { - "implementation"( "org.yaml:snakeyaml") { - version { strictly("1.26") } - because("Bukkit provides SnakeYaml") - } - } +// constraints { +// "implementation"( "org.yaml:snakeyaml") { +// version { strictly("1.26") } +// because("Bukkit provides SnakeYaml") +// } +// } "api"(project(":worldedit-libs:core")) "implementation"("de.schlichtherle:truezip:6.8.4") "implementation"("net.java.truevfs:truevfs-profile-default_2.13:0.12.1") "implementation"("org.mozilla:rhino-runtime:1.7.13") - "implementation"("org.yaml:snakeyaml") + "implementation"("org.yaml:snakeyaml:1.27") "implementation"("com.google.guava:guava") "implementation"("com.google.code.findbugs:jsr305:1.3.9") "implementation"("com.google.code.gson:gson") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java index cc613dac5b..7f966f0da8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.util.Identifiable; import com.sk89q.worldedit.util.auth.Subject; import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; import java.io.File; @@ -57,7 +58,9 @@ default String getDisplayName() { * @deprecated Use component-based functions (print) */ @Deprecated - void printRaw(String msg); + default void printRaw(String msg) { + print(TextComponent.of(msg)); + } /** * Print a WorldEdit message. @@ -66,7 +69,9 @@ default String getDisplayName() { * @deprecated Use component-based functions (printDebug) */ @Deprecated - void printDebug(String msg); + default void printDebug(String msg) { + printDebug(TextComponent.of(msg)); + } /** * Print a WorldEdit message. @@ -75,7 +80,9 @@ default String getDisplayName() { * @deprecated Use component-based functions (printInfo) */ @Deprecated - void print(String msg); + default void print(String msg) { + printInfo(TextComponent.of(msg)); + } /** * Print a WorldEdit error. @@ -84,7 +91,9 @@ default String getDisplayName() { * @deprecated Use component-based functions (printError) */ @Deprecated - void printError(String msg); + default void printError(String msg) { + printError(TextComponent.of(msg)); + } /** * Print a WorldEdit error. diff --git a/worldedit-libs/sponge/build.gradle.kts b/worldedit-libs/sponge/build.gradle.kts index 47bd7e59c5..a8d47c8024 100644 --- a/worldedit-libs/sponge/build.gradle.kts +++ b/worldedit-libs/sponge/build.gradle.kts @@ -4,6 +4,10 @@ constrainDependenciesToLibsCore() repositories { maven { name = "Sponge" + url = uri("https://repo-new.spongepowered.org/maven") + } + maven { + name = "Sponge-Old" url = uri("https://repo.spongepowered.org/maven") } } diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index 1bff90e437..f6de41d2dc 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -1,7 +1,9 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { + `java-library` id("org.spongepowered.gradle.plugin") + id("org.spongepowered.gradle.vanilla") } applyPlatformAndCoreConfiguration() @@ -15,34 +17,51 @@ convention.getPlugin(JavaPluginConvention::class.java).apply { repositories { maven { url = uri("https://repo.codemc.org/repository/maven-public") } + maven { url = uri("https://repo.spongepowered.org/repository/maven-public/") } } dependencies { - api(project(":worldedit-core")) - api(project(":worldedit-libs:sponge")) - api("org.spongepowered:spongeapi:7.1.0") - api("org.bstats:bstats-sponge:1.7") - testImplementation("org.mockito:mockito-core:1.9.0-rc1") + "api"(project(":worldedit-core")) + "api"(project(":worldedit-libs:sponge")) + "api"("org.spongepowered:spongeapi:8.0.0-SNAPSHOT") +// "implementation"("org.bstats:bstats-sponge:1.7") + "implementation"("org.apache.logging.log4j:log4j-slf4j-impl:2.11.2") + "implementation"("it.unimi.dsi:fastutil:${Versions.FAST_UTIL}") + "testImplementation"("org.mockito:mockito-core:1.9.0-rc1") } +minecraft { + version("1.16.5") + injectRepositories(false) +} + +//sponge { +// plugin { +// id = "worldedit" +// } +//} + addJarManifest(includeClasspath = true) tasks.named("shadowJar") { dependencies { - relocate ("org.bstats", "com.sk89q.worldedit.sponge.bstats") { - include(dependency("org.bstats:bstats-sponge:1.7")) + relocate("org.slf4j", "com.sk89q.worldedit.slf4j") + relocate("org.apache.logging.slf4j", "com.sk89q.worldedit.log4jbridge") + relocate("org.antlr.v4", "com.sk89q.worldedit.antlr4") + + include(dependency(":worldedit-core")) + include(dependency("org.slf4j:slf4j-api")) + include(dependency("org.apache.logging.log4j:log4j-slf4j-impl")) + include(dependency("org.antlr:antlr4-runtime")) +// relocate ("org.bstats", "com.sk89q.worldedit.sponge.bstats") { +// include(dependency("org.bstats:bstats-sponge:1.7")) +// } + relocate("it.unimi.dsi.fastutil", "com.sk89q.worldedit.sponge.fastutil") { + include(dependency("it.unimi.dsi:fastutil")) } } } -if (project.hasProperty("signing")) { - apply(plugin = "signing") - - configure { - sign("shadowJar") - } - - tasks.named("build").configure { - dependsOn("signShadowJar") - } +tasks.named("assemble").configure { + dependsOn("shadowJar") } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CUIChannelHandler.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CUIChannelHandler.java index 8e342f79ca..a36535ff8f 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CUIChannelHandler.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CUIChannelHandler.java @@ -20,36 +20,35 @@ package com.sk89q.worldedit.sponge; import com.sk89q.worldedit.LocalSession; -import org.spongepowered.api.Platform; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.entity.living.player.Player; -import org.spongepowered.api.network.ChannelBinding; -import org.spongepowered.api.network.ChannelBuf; -import org.spongepowered.api.network.PlayerConnection; -import org.spongepowered.api.network.RawDataListener; -import org.spongepowered.api.network.RemoteConnection; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.event.lifecycle.RegisterChannelEvent; +import org.spongepowered.api.network.EngineConnection; +import org.spongepowered.api.network.ServerPlayerConnection; +import org.spongepowered.api.network.channel.ChannelBuf; +import org.spongepowered.api.network.channel.raw.RawDataChannel; +import org.spongepowered.api.network.channel.raw.play.RawPlayDataHandler; import java.nio.charset.StandardCharsets; -public class CUIChannelHandler implements RawDataListener { - public static final String CUI_PLUGIN_CHANNEL = "worldedit:cui"; +public class CUIChannelHandler implements RawPlayDataHandler { + public static final ResourceKey CUI_PLUGIN_CHANNEL = ResourceKey.of("worldedit", "cui"); - private static ChannelBinding.RawDataChannel channel; + private static RawDataChannel channel; - public static void init() { - channel = Sponge.getChannelRegistrar().createRawChannel(SpongeWorldEdit.inst(), CUI_PLUGIN_CHANNEL); - channel.addListener(Platform.Type.SERVER, new CUIChannelHandler()); + public static void init(RegisterChannelEvent event) { + channel = event.register(CUI_PLUGIN_CHANNEL, RawDataChannel.class); + channel.play().addHandler(new CUIChannelHandler()); } - - public static ChannelBinding.RawDataChannel getActiveChannel() { + public static RawDataChannel getActiveChannel() { return channel; } @Override - public void handlePayload(ChannelBuf data, RemoteConnection connection, Platform.Type side) { - if (connection instanceof PlayerConnection) { - Player player = ((PlayerConnection) connection).getPlayer(); + public void handlePayload(ChannelBuf data, EngineConnection connection) { + if (connection instanceof ServerPlayerConnection) { + ServerPlayer player = ((ServerPlayerConnection) connection).getPlayer(); LocalSession session = SpongeWorldEdit.inst().getSession(player); diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java index 261d811b8d..1059d9562e 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java @@ -19,19 +19,22 @@ package com.sk89q.worldedit.sponge; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.util.PermissionCondition; +import com.sk89q.worldedit.util.formatting.WorldEditText; +import net.kyori.adventure.text.Component; import org.enginehub.piston.Command; -import org.spongepowered.api.command.CommandCallable; -import org.spongepowered.api.command.CommandSource; -import org.spongepowered.api.text.Text; +import org.spongepowered.api.command.CommandCause; +import org.spongepowered.api.entity.living.player.Player; import java.util.Collections; +import java.util.Locale; import java.util.Optional; import java.util.Set; import static com.sk89q.worldedit.sponge.SpongeTextAdapter.convert; -public abstract class CommandAdapter implements CommandCallable { +public abstract class CommandAdapter implements org.spongepowered.api.command.Command.Raw { private final Command command; protected CommandAdapter(Command command) { @@ -39,12 +42,12 @@ protected CommandAdapter(Command command) { } @Override - public boolean testPermission(CommandSource source) { + public boolean canExecute(CommandCause source) { Set permissions = command.getCondition().as(PermissionCondition.class) .map(PermissionCondition::getPermissions) .orElseGet(Collections::emptySet); for (String perm : permissions) { - if (source.hasPermission(perm)) { + if (source.getSubject().hasPermission(perm)) { return true; } } @@ -52,19 +55,28 @@ public boolean testPermission(CommandSource source) { } @Override - public Optional getShortDescription(CommandSource source) { + public Optional getShortDescription(CommandCause source) { + Locale locale = source.getAudience() instanceof Player + ? ((Player) source.getAudience()).getLocale() + : WorldEdit.getInstance().getConfiguration().defaultLocale; return Optional.of(command.getDescription()) - .map(desc -> SpongeTextAdapter.convert(desc, source.getLocale())); + .map(desc -> SpongeTextAdapter.convert(WorldEditText.format(desc, locale))); } @Override - public Optional getHelp(CommandSource source) { + public Optional getHelp(CommandCause source) { + Locale locale = source.getAudience() instanceof Player + ? ((Player) source.getAudience()).getLocale() + : WorldEdit.getInstance().getConfiguration().defaultLocale; return Optional.of(command.getFullHelp()) - .map(help -> SpongeTextAdapter.convert(help, source.getLocale())); + .map(help -> SpongeTextAdapter.convert(WorldEditText.format(help, locale))); } @Override - public Text getUsage(CommandSource source) { - return convert(command.getUsage(), source.getLocale()); + public Component getUsage(CommandCause source) { + Locale locale = source.getAudience() instanceof Player + ? ((Player) source.getAudience()).getLocale() + : WorldEdit.getInstance().getConfiguration().defaultLocale; + return convert(WorldEditText.format(command.getUsage(), locale)); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java index 5f720b679c..d7d43e0fb5 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeAdapter.java @@ -19,15 +19,50 @@ package com.sk89q.worldedit.sponge; -import com.flowpowered.math.vector.Vector3d; +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.registry.state.BooleanProperty; +import com.sk89q.worldedit.registry.state.DirectionalProperty; +import com.sk89q.worldedit.registry.state.EnumProperty; +import com.sk89q.worldedit.registry.state.IntegerProperty; +import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.item.ItemTypes; +import com.sk89q.worldedit.world.weather.WeatherType; +import com.sk89q.worldedit.world.weather.WeatherTypes; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.item.inventory.ItemStack; +import org.spongepowered.api.registry.RegistryHolder; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.state.BooleanStateProperty; +import org.spongepowered.api.state.EnumStateProperty; +import org.spongepowered.api.state.IntegerStateProperty; +import org.spongepowered.api.state.StateProperty; +import org.spongepowered.api.util.Direction; +import org.spongepowered.api.world.biome.Biome; +import org.spongepowered.api.world.schematic.PaletteTypes; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.math.vector.Vector3d; +import org.spongepowered.math.vector.Vector3i; + +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; @@ -39,30 +74,16 @@ public class SpongeAdapter { private SpongeAdapter() { } - /** - * Create a WorldEdit world from a Sponge extent. - * - * @param world the Sponge extent - * @return a WorldEdit world - */ - public static World checkWorld(org.spongepowered.api.world.extent.Extent world) { - checkNotNull(world); - if (world instanceof org.spongepowered.api.world.World) { - return adapt((org.spongepowered.api.world.World) world); - } else { - throw new IllegalArgumentException("Extent type is not a world"); - } - } - /** * Create a WorldEdit world from a Sponge world. * * @param world the Sponge world * @return a WorldEdit world */ - public static World adapt(org.spongepowered.api.world.World world) { + public static World adapt(ServerWorld world) { checkNotNull(world); - return SpongeWorldEdit.inst().getWorld(world); + + return new SpongeWorld(world); } /** @@ -71,7 +92,7 @@ public static World adapt(org.spongepowered.api.world.World world) { * @param player The Sponge player * @return The WorldEdit player */ - public static SpongePlayer adapt(Player player) { + public static SpongePlayer adapt(ServerPlayer player) { return SpongeWorldEdit.inst().wrapPlayer(player); } @@ -91,12 +112,12 @@ public static Player adapt(com.sk89q.worldedit.entity.Player player) { * @param world the WorldEdit world * @return a Sponge world */ - public static org.spongepowered.api.world.World adapt(World world) { + public static ServerWorld adapt(World world) { checkNotNull(world); if (world instanceof SpongeWorld) { return ((SpongeWorld) world).getWorld(); } else { - org.spongepowered.api.world.World match = Sponge.getServer().getWorld(world.getName()).orElse(null); + ServerWorld match = Sponge.getServer().getWorldManager().world(ResourceKey.resolve(world.getName())).orElse(null); if (match != null) { return match; } else { @@ -105,12 +126,36 @@ public static org.spongepowered.api.world.World adapt(World world) { } } - public static BiomeType adapt(org.spongepowered.api.world.biome.BiomeType biomeType) { - return BiomeTypes.get(biomeType.getId()); + public static ItemType adapt(org.spongepowered.api.item.ItemType itemType) { + return ItemTypes.get(itemType.key(RegistryTypes.ITEM_TYPE).getFormatted()); + } + + public static org.spongepowered.api.item.ItemType adapt(ItemType itemType) { + return RegistryTypes.ITEM_TYPE.get().findValue(ResourceKey.resolve(itemType.getId())).orElse(null); + } + + public static BlockType adapt(org.spongepowered.api.block.BlockType blockType) { + return BlockTypes.get(blockType.key(RegistryTypes.BLOCK_TYPE).getFormatted()); } - public static org.spongepowered.api.world.biome.BiomeType adapt(BiomeType biomeType) { - return Sponge.getRegistry().getType(org.spongepowered.api.world.biome.BiomeType.class, biomeType.getId()).orElse(null); + public static org.spongepowered.api.block.BlockType adapt(BlockType blockType) { + return RegistryTypes.BLOCK_TYPE.get().findValue(ResourceKey.resolve(blockType.getId())).orElse(null); + } + + public static WeatherType adapt(org.spongepowered.api.world.weather.WeatherType weatherType) { + return WeatherTypes.get(weatherType.key(RegistryTypes.WEATHER_TYPE).getFormatted()); + } + + public static org.spongepowered.api.world.weather.WeatherType adapt(WeatherType weatherType) { + return RegistryTypes.WEATHER_TYPE.get().findValue(ResourceKey.resolve(weatherType.getId())).orElse(null); + } + + public static BiomeType adapt(Biome biomeType, RegistryHolder registryHolder) { + return BiomeTypes.get(RegistryTypes.BIOME.keyFor(registryHolder, biomeType).getFormatted()); + } + + public static Biome adapt(BiomeType biomeType, RegistryHolder registryHolder) { + return RegistryTypes.BIOME.referenced(ResourceKey.resolve(biomeType.getId())).get(registryHolder); } /** @@ -119,11 +164,11 @@ public static org.spongepowered.api.world.biome.BiomeType adapt(BiomeType biomeT * @param location the Sponge location * @return a WorldEdit location */ - public static Location adapt(org.spongepowered.api.world.Location location, Vector3d rotation) { + public static Location adapt(ServerLocation location, Vector3d rotation) { checkNotNull(location); Vector3 position = asVector(location); return new Location( - adapt(location.getExtent()), + adapt(location.getWorld()), position, (float) rotation.getX(), (float) rotation.getY()); @@ -135,10 +180,10 @@ public static Location adapt(org.spongepowered.api.world.Location adapt(Location location) { + public static ServerLocation adapt(Location location) { checkNotNull(location); Vector3 position = location.toVector(); - return new org.spongepowered.api.world.Location<>( + return ServerLocation.of( adapt((World) location.getExtent()), position.getX(), position.getY(), position.getZ()); } @@ -160,7 +205,7 @@ public static Vector3d adaptRotation(Location location) { * @param location The Bukkit location * @return a WorldEdit vector */ - public static Vector3 asVector(org.spongepowered.api.world.Location location) { + public static Vector3 asVector(ServerLocation location) { checkNotNull(location); return Vector3.at(location.getX(), location.getY(), location.getZ()); } @@ -171,8 +216,99 @@ public static Vector3 asVector(org.spongepowered.api.world.Location location) { + public static BlockVector3 asBlockVector(ServerLocation location) { checkNotNull(location); return BlockVector3.at(location.getX(), location.getY(), location.getZ()); } + + /** + * Create a WorldEdit BlockVector3 from a Sponge Vector3i. + * + * @param vec The Sponge Vector3i + * @return The WorldEdit BlockVector3 + */ + public static BlockVector3 adapt(Vector3i vec) { + return BlockVector3.at(vec.getX(), vec.getY(), vec.getZ()); + } + + /** + * Create a Sponge Vector3i from a WorldEdit BlockVector3. + * + * @param vec The WorldEdit BlockVector3 + * @return The Sponge Vector3i + */ + public static Vector3i adapt(BlockVector3 vec) { + return new Vector3i(vec.getX(), vec.getY(), vec.getZ()); + } + + public static com.sk89q.worldedit.util.Direction adapt(Direction direction) { + if (direction == null) { + return null; + } + switch (direction) { + case NORTH: return com.sk89q.worldedit.util.Direction.NORTH; + case SOUTH: return com.sk89q.worldedit.util.Direction.SOUTH; + case WEST: return com.sk89q.worldedit.util.Direction.WEST; + case EAST: return com.sk89q.worldedit.util.Direction.EAST; + case DOWN: return com.sk89q.worldedit.util.Direction.DOWN; + case UP: + default: + return com.sk89q.worldedit.util.Direction.UP; + } + } + + @SuppressWarnings("unchecked") + public static Property adaptProperty(StateProperty property) { + if (property instanceof BooleanStateProperty) { + return new BooleanProperty(property.getName(), ImmutableList.copyOf(((BooleanStateProperty) property).getPossibleValues())); + } + if (property instanceof IntegerStateProperty) { + return new IntegerProperty(property.getName(), ImmutableList.copyOf(((IntegerStateProperty) property).getPossibleValues())); + } + if (property instanceof EnumStateProperty) { + if (property.getPossibleValues().stream().anyMatch(ent -> ent instanceof Direction)) { + return new DirectionalProperty(property.getName(), ((EnumStateProperty) property).getPossibleValues() + .stream() + .map(SpongeAdapter::adapt) + .collect(Collectors.toList())); + } else { + return new EnumProperty(property.getName(), ((EnumStateProperty) property).getPossibleValues().stream() + .map(Enum::name) + .collect(Collectors.toList())); + } + } + return new SpongePropertyAdapter<>(property); + } + + /** + * Create a WorldEdit BlockState from a Sponge BlockState. + * + * @param blockState The Sponge BlockState + * @return The WorldEdit BlockState + */ + public static BlockState adapt(org.spongepowered.api.block.BlockState blockState) { + checkNotNull(blockState); + + return BlockStateIdAccess.getBlockStateById(PaletteTypes.BLOCK_STATE_PALETTE.get().create(Sponge.getGame().registries(), RegistryTypes.BLOCK_TYPE).get(blockState).getAsInt()); + } + + private static final Int2ObjectMap spongeBlockStateCache = new Int2ObjectOpenHashMap<>(); + + /** + * Create a Sponge BlockState from a WorldEdit BlockStateHolder. + * + * @param block The WorldEdit BlockStateHolder + * @return The Sponge BlockState + */ + public static > org.spongepowered.api.block.BlockState adapt(B block) { + checkNotNull(block); + // Should never not have an ID for this BlockState. + int cacheKey = BlockStateIdAccess.getBlockStateId(block.toImmutableState()); + if (cacheKey == BlockStateIdAccess.invalidId()) { + cacheKey = block.hashCode(); + } + + return spongeBlockStateCache.computeIfAbsent(cacheKey, input -> PaletteTypes.BLOCK_STATE_PALETTE.get().create(Sponge.getGame().registries(), RegistryTypes.BLOCK_TYPE).get(input, Sponge.getGame().registries()).orElse(null)); + } + } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java index 39b8cfd2c8..7b1e523080 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java @@ -26,13 +26,8 @@ import com.sk89q.worldedit.util.auth.AuthorizationException; import com.sk89q.worldedit.util.formatting.WorldEditText; import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.adapter.spongeapi.TextAdapter; -import org.spongepowered.api.command.CommandSource; +import net.kyori.adventure.audience.Audience; import org.spongepowered.api.entity.living.player.Player; -import org.spongepowered.api.text.Text; -import org.spongepowered.api.text.format.TextColor; -import org.spongepowered.api.text.format.TextColors; -import org.spongepowered.api.text.serializer.TextSerializers; import java.io.File; import java.util.Locale; @@ -49,10 +44,10 @@ public class SpongeCommandSender implements Actor { */ private static final UUID DEFAULT_ID = UUID.fromString("a233eb4b-4cab-42cd-9fd9-7e7b9a3f74be"); - private final CommandSource sender; + private final Audience sender; private final SpongeWorldEdit plugin; - public SpongeCommandSender(SpongeWorldEdit plugin, CommandSource sender) { + public SpongeCommandSender(SpongeWorldEdit plugin, Audience sender) { checkNotNull(plugin); checkNotNull(sender); checkArgument(!(sender instanceof Player), "Cannot wrap a player"); @@ -68,42 +63,12 @@ public UUID getUniqueId() { @Override public String getName() { - return sender.getName(); - } - - @SuppressWarnings("deprecation") - @Override - public void printRaw(String msg) { - for (String part : msg.split("\n")) { - sender.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(part)); - } - } - - @Override - public void print(String msg) { - sendColorized(msg, TextColors.LIGHT_PURPLE); - } - - @Override - public void printDebug(String msg) { - sendColorized(msg, TextColors.GRAY); - } - - @Override - public void printError(String msg) { - sendColorized(msg, TextColors.RED); + return "Console"; } @Override public void print(Component component) { - TextAdapter.sendMessage(sender, WorldEditText.format(component, getLocale())); - } - - @SuppressWarnings("deprecation") - private void sendColorized(String msg, TextColor formatting) { - for (String part : msg.split("\n")) { - sender.sendMessage(Text.of(formatting, TextSerializers.LEGACY_FORMATTING_CODE.deserialize(part))); - } + sender.sendMessage(SpongeTextAdapter.convert(WorldEditText.format(component, getLocale()))); } @Override @@ -155,17 +120,17 @@ public SessionKey getSessionKey() { @Nullable @Override public String getName() { - return null; + return "Console"; } @Override public boolean isActive() { - return false; + return true; } @Override public boolean isPersistent() { - return false; + return true; } @Override diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntity.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntity.java index 532a366082..da7bb9eef5 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntity.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntity.java @@ -19,14 +19,15 @@ package com.sk89q.worldedit.sponge; -import com.flowpowered.math.vector.Vector3d; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.metadata.EntityProperties; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.NullWorld; -import org.spongepowered.api.world.World; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.math.vector.Vector3d; import java.lang.ref.WeakReference; import javax.annotation.Nullable; @@ -46,7 +47,8 @@ class SpongeEntity implements Entity { public BaseEntity getState() { org.spongepowered.api.entity.Entity entity = entityRef.get(); if (entity != null) { - return SpongeWorldEdit.inst().getAdapter().createBaseEntity(entity); + return null; + // TODO return SpongeWorldEdit.inst().getAdapter().createBaseEntity(entity); } else { return null; } @@ -56,10 +58,10 @@ public BaseEntity getState() { public Location getLocation() { org.spongepowered.api.entity.Entity entity = entityRef.get(); if (entity != null) { - org.spongepowered.api.world.Location entityLoc = entity.getLocation(); + ServerLocation entityLoc = (ServerLocation) entity.getLocation(); Vector3d entityRot = entity.getRotation(); - return SpongeWorldEdit.inst().getAdapter().adapt(entityLoc, entityRot); + return SpongeAdapter.adapt(entityLoc, entityRot); } else { return new Location(NullWorld.getInstance()); } @@ -79,7 +81,7 @@ public boolean setLocation(Location location) { public Extent getExtent() { org.spongepowered.api.entity.Entity entity = entityRef.get(); if (entity != null) { - return SpongeWorldEdit.inst().getAdapter().getWorld(entity.getWorld()); + return SpongeAdapter.adapt((ServerWorld) entity.getWorld()); } else { return NullWorld.getInstance(); } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntityProperties.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntityProperties.java index 7373ae642f..38547e446f 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntityProperties.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeEntityProperties.java @@ -20,29 +20,27 @@ package com.sk89q.worldedit.sponge; import com.sk89q.worldedit.entity.metadata.EntityProperties; -import org.spongepowered.api.data.key.Keys; +import org.spongepowered.api.data.Keys; import org.spongepowered.api.entity.Entity; import org.spongepowered.api.entity.ExperienceOrb; import org.spongepowered.api.entity.FallingBlock; import org.spongepowered.api.entity.Item; -import org.spongepowered.api.entity.explosive.PrimedTNT; +import org.spongepowered.api.entity.explosive.fused.PrimedTNT; import org.spongepowered.api.entity.hanging.ItemFrame; import org.spongepowered.api.entity.hanging.Painting; import org.spongepowered.api.entity.living.Ambient; import org.spongepowered.api.entity.living.ArmorStand; +import org.spongepowered.api.entity.living.ComplexLivingPart; import org.spongepowered.api.entity.living.Humanoid; import org.spongepowered.api.entity.living.Living; -import org.spongepowered.api.entity.living.Villager; import org.spongepowered.api.entity.living.animal.Animal; -import org.spongepowered.api.entity.living.complex.ComplexLivingPart; +import org.spongepowered.api.entity.living.aquatic.Aquatic; import org.spongepowered.api.entity.living.golem.Golem; import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.trader.Villager; import org.spongepowered.api.entity.projectile.Projectile; import org.spongepowered.api.entity.vehicle.Boat; import org.spongepowered.api.entity.vehicle.minecart.Minecart; -import org.spongepowered.api.text.Text; - -import java.util.Optional; import static com.google.common.base.Preconditions.checkNotNull; @@ -132,12 +130,12 @@ public boolean isGolem() { @Override public boolean isTamed() { - return entity.get(Keys.TAMED_OWNER).orElse(Optional.empty()).isPresent(); + return entity.get(Keys.TAMER).isPresent(); } @Override public boolean isTagged() { - return !entity.get(Keys.DISPLAY_NAME).orElse(Text.EMPTY).isEmpty(); + return entity.get(Keys.DISPLAY_NAME).isPresent(); } @Override @@ -152,6 +150,6 @@ public boolean isPasteable() { @Override public boolean isWaterCreature() { - return false; // TODO api8 + return entity instanceof Aquatic; } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePermissionsProvider.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePermissionsProvider.java index 0e8fc89c94..5d7961dc65 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePermissionsProvider.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePermissionsProvider.java @@ -20,26 +20,26 @@ package com.sk89q.worldedit.sponge; import org.spongepowered.api.Sponge; -import org.spongepowered.api.command.CommandCallable; -import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.service.permission.PermissionDescription; import org.spongepowered.api.service.permission.PermissionService; import org.spongepowered.api.service.permission.SubjectReference; public class SpongePermissionsProvider { - public boolean hasPermission(Player player, String permission) { + public boolean hasPermission(ServerPlayer player, String permission) { return player.hasPermission(permission); } - public void registerPermission(CommandCallable command, String permission) { - Sponge.getGame().getServiceManager().getRegistration(PermissionService.class).ifPresent((permissionService -> { - PermissionDescription.Builder permissionBuilder = permissionService.getProvider().newDescriptionBuilder(SpongeWorldEdit.inst()); + public void registerPermission(Command command, String permission) { + Sponge.getGame().getServiceProvider().getRegistration(PermissionService.class).ifPresent((permissionService -> { + PermissionDescription.Builder permissionBuilder = permissionService.service().newDescriptionBuilder(SpongeWorldEdit.container()); permissionBuilder.id(permission).register(); })); } - public String[] getGroups(Player player) { + public String[] getGroups(ServerPlayer player) { return player.getParents().stream() .map(SubjectReference::getSubjectIdentifier) .toArray(String[]::new); diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java index c033e31aca..b6a9b44153 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java @@ -19,8 +19,7 @@ package com.sk89q.worldedit.sponge; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.CommandEvent; @@ -32,18 +31,25 @@ import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.internal.command.CommandUtil; import com.sk89q.worldedit.sponge.config.SpongeConfiguration; +import com.sk89q.worldedit.sponge.registry.SpongeRegistries; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; +import net.kyori.adventure.text.Component; import org.enginehub.piston.Command; import org.enginehub.piston.CommandManager; +import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; -import org.spongepowered.api.command.CommandException; +import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.command.CommandResult; -import org.spongepowered.api.command.CommandSource; -import org.spongepowered.api.entity.EntityType; +import org.spongepowered.api.command.exception.CommandException; +import org.spongepowered.api.command.parameter.ArgumentReader; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.scheduler.Task; -import org.spongepowered.api.world.Location; +import org.spongepowered.api.util.Ticks; +import org.spongepowered.api.world.server.ServerWorld; import java.util.ArrayList; import java.util.Collection; @@ -61,6 +67,8 @@ class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { private final SpongeWorldEdit mod; private boolean hookingEvents = false; + private RegisterCommandEvent commandRegisterEvent; + SpongePlatform(SpongeWorldEdit mod) { this.mod = mod; } @@ -76,13 +84,12 @@ public Registries getRegistries() { @Override public int getDataVersion() { - // TODO add to adapter - org.spongepowered.common.data.util.DataUtil#MINECRAFT_DATA_VERSION - return 1631; + return Sponge.getPlatform().getMinecraftVersion().getDataVersion().orElse(-1); } @Override public boolean isValidMobType(String type) { - return Sponge.getRegistry().getType(EntityType.class, type).isPresent(); + return RegistryTypes.ENTITY_TYPE.get().findEntry(ResourceKey.resolve(type)).isPresent(); } @Override @@ -93,16 +100,27 @@ public void reload() { @Override public int schedule(long delay, long period, Runnable task) { - Task.builder().delayTicks(delay).intervalTicks(period).execute(task).submit(SpongeWorldEdit.inst()); - return 0; // TODO This isn't right, but we only check for -1 values + try { + Task.builder() + .delay(Ticks.of(delay)) + .interval(Ticks.of(period)) + .execute(task) + .plugin(mod.getContainer()) + .build(); + } catch (IllegalStateException e) { + // Thrown when it failed to schedule + SpongeWorldEdit.inst().getLogger().warn("Failed to schedule a task", e); + return -1; + } + return 0; } @Override public List getWorlds() { - Collection worlds = Sponge.getServer().getWorlds(); + Collection worlds = Sponge.getServer().getWorldManager().worlds(); List ret = new ArrayList<>(worlds.size()); - for (org.spongepowered.api.world.World world : worlds) { - ret.add(SpongeWorldEdit.inst().getAdapter().getWorld(world)); + for (ServerWorld world : worlds) { + ret.add(SpongeAdapter.adapt(world)); } return ret; } @@ -113,7 +131,7 @@ public Player matchPlayer(Player player) { if (player instanceof SpongePlayer) { return player; } else { - Optional optPlayer = Sponge.getServer().getPlayer(player.getUniqueId()); + Optional optPlayer = Sponge.getServer().getPlayer(player.getUniqueId()); return optPlayer.map(player1 -> new SpongePlayer(this, player1)).orElse(null); } } @@ -124,9 +142,9 @@ public World matchWorld(World world) { if (world instanceof SpongeWorld) { return world; } else { - for (org.spongepowered.api.world.World ws : Sponge.getServer().getWorlds()) { - if (ws.getName().equals(world.getName())) { - return SpongeWorldEdit.inst().getAdapter().getWorld(ws); + for (ServerWorld ws : Sponge.getServer().getWorldManager().worlds()) { + if (ws.getKey().toString().equals(world.getName())) { + return SpongeAdapter.adapt(ws); } } @@ -134,27 +152,52 @@ public World matchWorld(World world) { } } + void setCommandRegisterEvent(RegisterCommandEvent commandRegisterEvent) { + this.commandRegisterEvent = commandRegisterEvent; + } + + private String rebuildArguments(String commandLabel, ArgumentReader.Mutable args) { + int plSep = commandLabel.indexOf(":"); + if (plSep >= 0 && plSep < commandLabel.length() + 1) { + commandLabel = commandLabel.substring(plSep + 1); + } + + StringBuilder sb = new StringBuilder("/").append(commandLabel); + if (args.getTotalLength() > 0) { + sb.append(" ").append(args.getInput()); + } + return sb.toString(); + } + @Override public void registerCommands(CommandManager manager) { + if (commandRegisterEvent == null) { + return; + } + for (Command command : manager.getAllCommands().collect(toList())) { CommandAdapter adapter = new CommandAdapter(command) { @Override - public CommandResult process(CommandSource source, String arguments) throws org.spongepowered.api.command.CommandException { - CommandEvent weEvent = new CommandEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getName() + " " + arguments); + public CommandResult process(CommandCause source, ArgumentReader.Mutable arguments) throws CommandException { + CommandEvent weEvent = new CommandEvent(SpongeWorldEdit.inst().wrapCommandCause(source), rebuildArguments(command.getName(), arguments)); WorldEdit.getInstance().getEventBus().post(weEvent); return weEvent.isCancelled() ? CommandResult.success() : CommandResult.empty(); } @Override - public List getSuggestions(CommandSource source, String arguments, @Nullable Location targetPosition) throws CommandException { - CommandSuggestionEvent weEvent = new CommandSuggestionEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getName() + " " + arguments); + public List getSuggestions(CommandCause cause, ArgumentReader.Mutable arguments) throws CommandException { + String args = rebuildArguments(command.getName(), arguments); + CommandSuggestionEvent weEvent = new CommandSuggestionEvent(SpongeWorldEdit.inst().wrapCommandCause(cause), args); WorldEdit.getInstance().getEventBus().post(weEvent); - return CommandUtil.fixSuggestions(arguments, weEvent.getSuggestions()); + return CommandUtil.fixSuggestions(args, weEvent.getSuggestions()); + } + + @Override + public Optional getExtendedDescription(CommandCause cause) { + return Optional.empty(); } }; - ImmutableList.Builder aliases = ImmutableList.builder(); - aliases.add(command.getName()).addAll(command.getAliases()); - Sponge.getCommandManager().register(SpongeWorldEdit.inst(), adapter, aliases.build()); + commandRegisterEvent.register(SpongeWorldEdit.container(), adapter, command.getName(), command.getAliases().toArray(new String[0])); } } @@ -201,15 +244,22 @@ public Map getCapabilities() { return capabilities; } + private static final Set SUPPORTED_SIDE_EFFECTS_NO_MIXIN = Sets.immutableEnumSet( + SideEffect.VALIDATION, + SideEffect.ENTITY_AI, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS + ); + @Override public Set getSupportedSideEffects() { - return ImmutableSet.of(); + return SUPPORTED_SIDE_EFFECTS_NO_MIXIN; } @Override public Collection getConnectedUsers() { List users = new ArrayList<>(); - for (org.spongepowered.api.entity.living.player.Player player : Sponge.getServer().getOnlinePlayers()) { + for (ServerPlayer player : Sponge.getServer().getOnlinePlayers()) { users.add(new SpongePlayer(this, player)); } return users; diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java index f0f814d74f..a5400cadb4 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.sponge; -import com.flowpowered.math.vector.Vector3d; import com.sk89q.util.StringUtil; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; @@ -33,34 +32,30 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.WorldEditText; import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.adapter.spongeapi.TextAdapter; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; -import com.sk89q.worldedit.world.item.ItemTypes; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.data.key.Keys; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.type.HandTypes; import org.spongepowered.api.entity.living.player.Player; -import org.spongepowered.api.item.ItemType; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.api.text.Text; -import org.spongepowered.api.text.format.TextColor; -import org.spongepowered.api.text.format.TextColors; -import org.spongepowered.api.text.serializer.TextSerializers; -import org.spongepowered.api.world.World; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.math.vector.Vector3d; import java.nio.charset.StandardCharsets; import java.util.Locale; -import java.util.Optional; import java.util.UUID; import javax.annotation.Nullable; public class SpongePlayer extends AbstractPlayerActor { - private final Player player; + private final ServerPlayer player; - protected SpongePlayer(SpongePlatform platform, Player player) { + protected SpongePlayer(SpongePlatform platform, ServerPlayer player) { this.player = player; ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId()); } @@ -72,9 +67,9 @@ public UUID getUniqueId() { @Override public BaseItemStack getItemInHand(HandSide handSide) { - Optional is = this.player.getItemInHand(handSide == HandSide.MAIN_HAND - ? HandTypes.MAIN_HAND : HandTypes.OFF_HAND); - return is.map(itemStack -> new BaseItemStack(ItemTypes.get(itemStack.getType().getId()))).orElse(null); + ItemStack is = this.player.getItemInHand(handSide == HandSide.MAIN_HAND + ? HandTypes.MAIN_HAND.get() : HandTypes.OFF_HAND.get()); + return new BaseItemStack(SpongeAdapter.adapt(is.getType())); } @Override @@ -82,10 +77,9 @@ public String getName() { return this.player.getName(); } - @SuppressWarnings("deprecation") @Override public String getDisplayName() { - return player.getDisplayNameData().displayName().getDirect().map(TextSerializers.LEGACY_FORMATTING_CODE::serialize).orElse(getName()); + return player.get(Keys.DISPLAY_NAME).map(LegacyComponentSerializer.legacyAmpersand()::serialize).orElse(getName()); } @Override @@ -95,10 +89,10 @@ public BaseEntity getState() { @Override public Location getLocation() { - org.spongepowered.api.world.Location entityLoc = this.player.getLocation(); + ServerLocation entityLoc = (ServerLocation) this.player.getLocation(); Vector3d entityRot = this.player.getRotation(); - return SpongeWorldEdit.inst().getAdapter().adapt(entityLoc, entityRot); + return SpongeAdapter.adapt(entityLoc, entityRot); } @Override @@ -108,13 +102,13 @@ public boolean setLocation(Location location) { @Override public com.sk89q.worldedit.world.World getWorld() { - return SpongeWorldEdit.inst().getAdapter().getWorld(player.getWorld()); + return SpongeAdapter.adapt(player.getWorld()); } @Override public void giveItem(BaseItemStack itemStack) { this.player.getInventory().offer( - ItemStack.of(Sponge.getGame().getRegistry().getType(ItemType.class, itemStack.getType().getId()).get(), + ItemStack.of(SpongeAdapter.adapt(itemStack.getType()), itemStack.getAmount()) ); } @@ -128,45 +122,17 @@ public void dispatchCUIEvent(CUIEvent event) { } String finalData = send; - CUIChannelHandler.getActiveChannel().sendTo(player, buffer -> buffer.writeBytes(finalData.getBytes(StandardCharsets.UTF_8))); - } - - @Override - public void printRaw(String msg) { - for (String part : msg.split("\n")) { - this.player.sendMessage(TextSerializers.FORMATTING_CODE.deserialize(part)); - } - } - - @Override - public void printDebug(String msg) { - sendColorized(msg, TextColors.GRAY); - } - - @Override - public void print(String msg) { - sendColorized(msg, TextColors.LIGHT_PURPLE); - } - - @Override - public void printError(String msg) { - sendColorized(msg, TextColors.RED); + CUIChannelHandler.getActiveChannel().play().sendTo(player, buffer -> buffer.writeBytes(finalData.getBytes(StandardCharsets.UTF_8))); } @Override public void print(Component component) { - TextAdapter.sendMessage(player, WorldEditText.format(component, getLocale())); - } - - private void sendColorized(String msg, TextColor formatting) { - for (String part : msg.split("\n")) { - this.player.sendMessage(Text.of(formatting, TextSerializers.FORMATTING_CODE.deserialize(part))); - } + player.sendMessage(SpongeTextAdapter.convert(WorldEditText.format(component, getLocale()))); } @Override public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { - org.spongepowered.api.world.Location loc = new org.spongepowered.api.world.Location<>( + ServerLocation loc = ServerLocation.of( this.player.getWorld(), pos.getX(), pos.getY(), pos.getZ() ); @@ -196,13 +162,15 @@ public T getFacet(Class cls) { @Override public GameMode getGameMode() { - return GameModes.get(player.getGameModeData().type().get().getId()); + return GameModes.get(player.get(Keys.GAME_MODE).get().key(RegistryTypes.GAME_MODE).getFormatted()); } @Override public void setGameMode(GameMode gameMode) { - player.getGameModeData().type().set(Sponge.getRegistry().getType(org.spongepowered.api.entity.living.player.gamemode.GameMode.class, - gameMode.getId()).get()); + player.offer( + Keys.GAME_MODE, + RegistryTypes.GAME_MODE.get().findValue(ResourceKey.resolve(gameMode.getId())).get() + ); } @Override @@ -217,11 +185,11 @@ public void setFlying(boolean flying) { @Override public > void sendFakeBlock(BlockVector3 pos, B block) { - org.spongepowered.api.world.Location loc = player.getWorld().getLocation(pos.getX(), pos.getY(), pos.getZ()); + ServerLocation loc = player.getWorld().getLocation(pos.getX(), pos.getY(), pos.getZ()); if (block == null) { player.sendBlockChange(loc.getBlockPosition(), loc.getBlock()); } else { - // TODO + // TODO via adapter // player.sendBlockChange(loc, BukkitAdapter.adapt(block)); // if (block instanceof BaseBlock && ((BaseBlock) block).hasNbtData()) { // BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePropertyAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePropertyAdapter.java new file mode 100644 index 0000000000..9b8dbf56e3 --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePropertyAdapter.java @@ -0,0 +1,75 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * 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 com.sk89q.worldedit.sponge; + +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.registry.state.Property; +import org.spongepowered.api.state.StateProperty; + +import java.util.List; +import java.util.Optional; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; + +public class SpongePropertyAdapter> implements Property { + + private final StateProperty property; + private final List values; + + public SpongePropertyAdapter(StateProperty property) { + this.property = property; + this.values = ImmutableList.copyOf(property.getPossibleValues()); + } + + @Override + public String getName() { + return this.property.getName(); + } + + @Override + public List getValues() { + return this.values; + } + + @Nullable + @Override + public T getValueFor(String string) throws IllegalArgumentException { + Optional val = property.parseValue(string); + checkArgument(val.isPresent(), "%s has no value for %s", getName(), string); + return val.get(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return getName().equals(((Property) o).getName()); + } + + @Override + public int hashCode() { + return property.getName().hashCode(); + } +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeTextAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeTextAdapter.java index 1731f98d13..0f384f7774 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeTextAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeTextAdapter.java @@ -19,19 +19,17 @@ package com.sk89q.worldedit.sponge; -import com.sk89q.worldedit.util.formatting.WorldEditText; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; -import org.spongepowered.api.text.Text; -import org.spongepowered.api.text.serializer.TextSerializers; - -import java.util.Locale; public class SpongeTextAdapter { - public static Text convert(Component component, Locale locale) { - component = WorldEditText.format(component, locale); - return TextSerializers.JSON.deserialize(GsonComponentSerializer.INSTANCE.serialize(component)); + public static net.kyori.adventure.text.Component convert(Component component) { + return net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(GsonComponentSerializer.INSTANCE.serialize(component)); + } + + public static Component convert(net.kyori.adventure.text.Component component) { + return GsonComponentSerializer.INSTANCE.deserialize(net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().serialize(component)); } private SpongeTextAdapter() { diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java index 8aead8e81e..9483a9308b 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorld.java @@ -19,8 +19,9 @@ package com.sk89q.worldedit.sponge; -import com.flowpowered.math.vector.Vector3d; -import com.flowpowered.math.vector.Vector3i; +import com.google.common.collect.Sets; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; @@ -29,8 +30,11 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.sponge.internal.SpongeWorldNativeAccess; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.WorldUnloadedException; @@ -39,29 +43,27 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.weather.WeatherType; -import com.sk89q.worldedit.world.weather.WeatherTypes; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.block.BlockSnapshot; -import org.spongepowered.api.block.BlockState; -import org.spongepowered.api.block.BlockType; -import org.spongepowered.api.block.BlockTypes; -import org.spongepowered.api.block.tileentity.TileEntity; -import org.spongepowered.api.data.key.Keys; -import org.spongepowered.api.data.property.block.GroundLuminanceProperty; -import org.spongepowered.api.data.property.block.SkyLuminanceProperty; +import net.minecraft.server.level.ServerLevel; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.block.entity.BlockEntity; +import org.spongepowered.api.block.entity.carrier.CarrierBlockEntity; import org.spongepowered.api.entity.EntityType; import org.spongepowered.api.entity.EntityTypes; -import org.spongepowered.api.world.BlockChangeFlags; -import org.spongepowered.api.world.World; -import org.spongepowered.api.world.weather.Weather; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.util.AABB; +import org.spongepowered.api.util.Ticks; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.api.world.server.ServerWorld; +import org.spongepowered.api.world.server.WorldTemplate; +import org.spongepowered.math.vector.Vector3d; +import org.spongepowered.math.vector.Vector3i; import java.lang.ref.WeakReference; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Locale; -import java.util.Map; -import java.util.Optional; +import java.util.Set; import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; @@ -69,18 +71,22 @@ /** * An adapter to Minecraft worlds for WorldEdit. */ -public abstract class SpongeWorld extends AbstractWorld { +public class SpongeWorld extends AbstractWorld { - private final WeakReference worldRef; + private final WeakReference worldRef; + private final WeakReference nativeWorldRef; + private final SpongeWorldNativeAccess worldNativeAccess; /** * Construct a new world. * * @param world the world */ - protected SpongeWorld(World world) { + protected SpongeWorld(ServerWorld world) { checkNotNull(world); this.worldRef = new WeakReference<>(world); + this.nativeWorldRef = new WeakReference<>((ServerLevel) world); + this.worldNativeAccess = new SpongeWorldNativeAccess(nativeWorldRef); } /** @@ -89,8 +95,8 @@ protected SpongeWorld(World world) { * @return the world * @throws WorldEditException thrown if a reference to the world was lost (i.e. world was unloaded) */ - public World getWorldChecked() throws WorldEditException { - World world = worldRef.get(); + public ServerWorld getWorldChecked() throws WorldEditException { + ServerWorld world = worldRef.get(); if (world != null) { return world; } else { @@ -104,8 +110,8 @@ public World getWorldChecked() throws WorldEditException { * @return the world * @throws RuntimeException thrown if a reference to the world was lost (i.e. world was unloaded) */ - public World getWorld() { - World world = worldRef.get(); + public ServerWorld getWorld() { + ServerWorld world = worldRef.get(); if (world != null) { return world; } else { @@ -113,15 +119,24 @@ public World getWorld() { } } + public ServerLevel getNativeWorld() { + ServerLevel world = nativeWorldRef.get(); + if (world != null) { + return world; + } else { + throw new RuntimeException("The reference to the native world was lost (i.e. the world may have been unloaded)"); + } + } + @Override public String getName() { - return getWorld().getName(); + return getWorld().getKey().toString(); } @Override public String getId() { return getName().replace(" ", "_").toLowerCase(Locale.ROOT) - + getWorld().getDimension().getType().getName().toLowerCase(Locale.ROOT); + + getWorld().asTemplate().getKey().getFormatted().toLowerCase(Locale.ROOT); } @Override @@ -129,63 +144,20 @@ public Path getStoragePath() { return getWorld().getDirectory(); } - @SuppressWarnings("WeakerAccess") - protected BlockState getBlockState(BlockStateHolder block) { - if (block instanceof com.sk89q.worldedit.world.block.BlockState) { - BlockState state = Sponge.getRegistry().getType(BlockType.class, block.getBlockType().getId()).orElse(BlockTypes.AIR).getDefaultState(); - for (Map.Entry, Object> entry : block.getStates().entrySet()) { - // TODO Convert across states - } - return state; - } else { - throw new UnsupportedOperationException("Missing Sponge adapter for WorldEdit!"); - } - } - - @SuppressWarnings("WeakerAccess") - protected abstract void applyTileEntityData(TileEntity entity, BaseBlock block); - - private static final BlockSnapshot.Builder builder = BlockSnapshot.builder(); - @Override - public > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { - checkNotNull(position); - checkNotNull(block); - - World world = getWorldChecked(); - - // First set the block - Vector3i pos = new Vector3i(position.getX(), position.getY(), position.getZ()); - BlockState newState = getBlockState(block); - - BlockSnapshot snapshot = builder.reset() - .blockState(newState) - .position(pos) - .world(world.getProperties()) - .build(); - - snapshot.restore(true, notifyAndLight ? BlockChangeFlags.ALL : BlockChangeFlags.NONE); - - // Create the TileEntity - if (block instanceof BaseBlock) { - BaseBlock baseBlock = (BaseBlock) block; - if (baseBlock.getNbtReference() != null) { - // Kill the old TileEntity - world.getTileEntity(pos).ifPresent(tileEntity -> applyTileEntityData(tileEntity, baseBlock)); - } - } - - return true; + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { + clearContainerBlockContents(position); + return worldNativeAccess.setBlock(position, block, sideEffects); } @Override - public boolean notifyAndLightBlock(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType) throws WorldEditException { - // TODO Move this to adapter - return false; + public Set applySideEffects(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { + worldNativeAccess.applySideEffects(position, previousType, sideEffectSet); + return Sets.intersection(SpongeWorldEdit.inst().getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply()); } @Override - public boolean regenerate(Region region, Extent extent, RegenOptions options) { + public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { return false; } @@ -193,24 +165,44 @@ public boolean regenerate(Region region, Extent extent, RegenOptions options) { public int getBlockLightLevel(BlockVector3 position) { checkNotNull(position); - BlockState state = getWorld().getBlock(new Vector3i(position.getX(), position.getY(), position.getZ())); + return getWorld().getLight(new Vector3i(position.getX(), position.getY(), position.getZ())); + } - Optional groundLuminanceProperty = state.getProperty(GroundLuminanceProperty.class); - Optional skyLuminanceProperty = state.getProperty(SkyLuminanceProperty.class); + @Override + public boolean clearContainerBlockContents(BlockVector3 position) { + checkNotNull(position); + if (!getBlock(position).getBlockType().getMaterial().hasContainer()) { + return false; + } - if (!groundLuminanceProperty.isPresent() || !skyLuminanceProperty.isPresent()) { - return 0; + BlockEntity tile = getWorld().getBlockEntity(SpongeAdapter.adapt(position)).orElse(null); + if (tile instanceof CarrierBlockEntity) { + ((CarrierBlockEntity) tile).getInventory().clear(); + return true; } + return false; + } - //noinspection ConstantConditions - return (int) Math.max(groundLuminanceProperty.get().getValue(), skyLuminanceProperty.get().getValue()); + @Override + public com.sk89q.worldedit.world.block.BlockState getBlock(BlockVector3 position) { + return SpongeAdapter.adapt(getWorld().getBlock(position.getX(), position.getY(), position.getZ())); + } + @Override + public BaseBlock getFullBlock(BlockVector3 position) { + // TODO NBT Data + return SpongeAdapter.adapt(getWorld().getBlock(position.getX(), position.getY(), position.getZ())).toBaseBlock(); } @Override public BiomeType getBiome(BlockVector3 position) { checkNotNull(position); - return SpongeAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ())); + return SpongeAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ()), getWorld().registries()); + } + + @Override + public boolean fullySupports3DBiomes() { + return !getWorld().asTemplate().getKey().equals(WorldTemplate.overworld().getKey()); } @Override @@ -218,7 +210,7 @@ public boolean setBiome(BlockVector3 position, BiomeType biome) { checkNotNull(position); checkNotNull(biome); - getWorld().setBiome(position.getBlockX(), position.getY(), position.getBlockZ(), SpongeAdapter.adapt(biome)); + getWorld().setBiome(position.getBlockX(), position.getY(), position.getBlockZ(), SpongeAdapter.adapt(biome, getWorld().registries())); return true; } @@ -232,17 +224,18 @@ public void dropItem(Vector3 position, BaseItemStack item) { } org.spongepowered.api.entity.Entity entity = getWorld().createEntity( - EntityTypes.ITEM, + EntityTypes.ITEM.get(), new Vector3d(position.getX(), position.getY(), position.getZ()) ); - entity.offer(Keys.REPRESENTED_ITEM, SpongeWorldEdit.toSpongeItemStack(item).createSnapshot()); + // TODO + // entity.offer(Keys.ITEM_STACK_SNAPSHOT, SpongeAdapter.adapt(item).createSnapshot()); getWorld().spawnEntity(entity); } @Override public void simulateBlockMine(BlockVector3 position) { - // TODO + getWorld().destroyBlock(SpongeAdapter.adapt(position), true); } @Override @@ -251,6 +244,11 @@ public boolean canPlaceAt(BlockVector3 position, com.sk89q.worldedit.world.block return true; } + @Override + public boolean regenerate(Region region, Extent extent, RegenOptions options) { + return false; + } + @Override public int hashCode() { return getWorld().hashCode(); @@ -262,8 +260,8 @@ public boolean equals(Object o) { return false; } else if ((o instanceof SpongeWorld)) { SpongeWorld other = ((SpongeWorld) o); - World otherWorld = other.worldRef.get(); - World thisWorld = worldRef.get(); + ServerWorld otherWorld = other.worldRef.get(); + ServerWorld thisWorld = worldRef.get(); return otherWorld != null && otherWorld.equals(thisWorld); } else { return o instanceof com.sk89q.worldedit.world.World @@ -274,9 +272,9 @@ public boolean equals(Object o) { @Override public List getEntities(Region region) { List entities = new ArrayList<>(); - for (org.spongepowered.api.entity.Entity entity : getWorld().getEntities()) { - org.spongepowered.api.world.Location loc = entity.getLocation(); - if (region.contains(BlockVector3.at(loc.getX(), loc.getY(), loc.getZ()))) { + // This region may not be cuboid + for (org.spongepowered.api.entity.Entity entity : getWorld().getEntities(AABB.of(getWorld().getBlockMin(), getWorld().getBlockMax()))) { + if (region.contains(SpongeAdapter.adapt(entity.getLocation().getBlockPosition()))) { entities.add(new SpongeEntity(entity)); } } @@ -286,20 +284,23 @@ public List getEntities(Region region) { @Override public List getEntities() { List entities = new ArrayList<>(); - for (org.spongepowered.api.entity.Entity entity : getWorld().getEntities()) { + for (org.spongepowered.api.entity.Entity entity : getWorld().getEntities(AABB.of(getWorld().getBlockMin(), getWorld().getBlockMax()))) { entities.add(new SpongeEntity(entity)); } return entities; } - protected abstract void applyEntityData(org.spongepowered.api.entity.Entity entity, BaseEntity data); + protected void applyEntityData(org.spongepowered.api.entity.Entity entity, BaseEntity data) { + // TODO Adapter + } @Nullable @Override public Entity createEntity(Location location, BaseEntity entity) { - World world = getWorld(); + ServerWorld world = getWorld(); + - EntityType entityType = Sponge.getRegistry().getType(EntityType.class, entity.getType().getId()).get(); + EntityType entityType = RegistryTypes.ENTITY_TYPE.get().findValue(ResourceKey.resolve(entity.getType().getId())).get(); Vector3d pos = new Vector3d(location.getX(), location.getY(), location.getZ()); org.spongepowered.api.entity.Entity newEnt = world.createEntity(entityType, pos); @@ -311,7 +312,7 @@ public Entity createEntity(Location location, BaseEntity entity) { Vector3 dir = location.getDirection(); newEnt.setLocationAndRotation( - new org.spongepowered.api.world.Location<>(getWorld(), pos), + ServerLocation.of(getWorld(), pos), new Vector3d(dir.getX(), dir.getY(), dir.getZ()) ); @@ -324,27 +325,27 @@ public Entity createEntity(Location location, BaseEntity entity) { @Override public WeatherType getWeather() { - return WeatherTypes.get(getWorld().getWeather().getId()); + return SpongeAdapter.adapt(getWorld().weather().type()); } @Override public long getRemainingWeatherDuration() { - return getWorld().getRemainingDuration(); + return getWorld().weather().remainingDuration().getTicks(); } @Override public void setWeather(WeatherType weatherType) { - getWorld().setWeather(Sponge.getRegistry().getType(Weather.class, weatherType.getId()).get()); + getWorld().setWeather(SpongeAdapter.adapt(weatherType)); } @Override public void setWeather(WeatherType weatherType, long duration) { - getWorld().setWeather(Sponge.getRegistry().getType(Weather.class, weatherType.getId()).get(), duration); + getWorld().setWeather(SpongeAdapter.adapt(weatherType), Ticks.of(duration)); } @Override public BlockVector3 getSpawnPosition() { - return SpongeAdapter.asBlockVector(getWorld().getSpawnLocation()); + return SpongeAdapter.adapt(getWorld().getProperties().spawnPosition()); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java index 889a9cf83a..b26c816ff6 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeWorldEdit.java @@ -22,47 +22,40 @@ import com.google.inject.Inject; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.event.platform.SessionIdleEvent; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.internal.anvil.ChunkDeleter; -import com.sk89q.worldedit.sponge.adapter.AdapterLoadException; -import com.sk89q.worldedit.sponge.adapter.SpongeImplAdapter; -import com.sk89q.worldedit.sponge.adapter.SpongeImplLoader; import com.sk89q.worldedit.sponge.config.SpongeConfiguration; -import org.bstats.sponge.Metrics2; +import net.kyori.adventure.audience.Audience; import org.slf4j.Logger; -import org.spongepowered.api.Sponge; +import org.slf4j.LoggerFactory; +import org.spongepowered.api.Server; import org.spongepowered.api.block.BlockSnapshot; import org.spongepowered.api.block.BlockType; import org.spongepowered.api.block.BlockTypes; -import org.spongepowered.api.command.CommandSource; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandCause; import org.spongepowered.api.config.ConfigDir; -import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.filter.cause.Root; -import org.spongepowered.api.event.game.state.GameAboutToStartServerEvent; -import org.spongepowered.api.event.game.state.GameInitializationEvent; -import org.spongepowered.api.event.game.state.GamePostInitializationEvent; -import org.spongepowered.api.event.game.state.GamePreInitializationEvent; -import org.spongepowered.api.event.game.state.GameStartedServerEvent; -import org.spongepowered.api.event.game.state.GameStoppingServerEvent; import org.spongepowered.api.event.item.inventory.InteractItemEvent; -import org.spongepowered.api.event.network.ClientConnectionEvent; -import org.spongepowered.api.item.ItemType; -import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.api.plugin.Plugin; -import org.spongepowered.api.plugin.PluginContainer; +import org.spongepowered.api.event.lifecycle.ConstructPluginEvent; +import org.spongepowered.api.event.lifecycle.RegisterChannelEvent; +import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.event.lifecycle.StartedEngineEvent; +import org.spongepowered.api.event.lifecycle.StartingEngineEvent; +import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; +import org.spongepowered.api.event.network.ServerSideConnectionEvent; +import org.spongepowered.api.registry.RegistryTypes; import org.spongepowered.api.scheduler.Task; -import org.spongepowered.api.world.Location; -import org.spongepowered.api.world.World; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.jvm.Plugin; -import java.io.File; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Optional; @@ -74,15 +67,12 @@ /** * The Sponge implementation of WorldEdit. */ -@Plugin(id = SpongeWorldEdit.MOD_ID, name = "WorldEdit", - description = "WorldEdit is an easy-to-use in-game world editor for Minecraft", - url = "https://enginehub.org/worldedit/") +@Plugin(value = SpongeWorldEdit.MOD_ID) public class SpongeWorldEdit { - @Inject - private Logger logger; + private Logger logger = LoggerFactory.getLogger(SpongeWorldEdit.class); - private final Metrics2 metrics; + // private final Metrics2 metrics; public static final String MOD_ID = "worldedit"; private static final int BSTATS_PLUGIN_ID = 3329; @@ -103,46 +93,37 @@ public static SpongeWorldEdit inst() { } private SpongePlatform platform; - private SpongeImplAdapter spongeAdapter; @Inject private SpongeConfiguration config; @Inject @ConfigDir(sharedRoot = false) - private File workingDir; + private Path workingDir; + // Metrics2.Factory metricsFactory <- from constructor params @Inject - public SpongeWorldEdit(Metrics2.Factory metricsFactory) { + public SpongeWorldEdit() { inst = this; - metrics = metricsFactory.make(BSTATS_PLUGIN_ID); + // metrics = metricsFactory.make(BSTATS_PLUGIN_ID); } @Listener - public void preInit(GamePreInitializationEvent event) { + public void preInit(ConstructPluginEvent event) { // Load configuration config.load(); - Task.builder().interval(30, TimeUnit.SECONDS).execute(ThreadSafeCache.getInstance()).submit(this); - } - - @Listener - public void init(GameInitializationEvent event) { - CUIChannelHandler.init(); - } + Task.builder() + .interval(30, TimeUnit.SECONDS) + .execute(ThreadSafeCache.getInstance()) + .plugin(this.container) + .build(); - @Listener - public void postInit(GamePostInitializationEvent event) { - logger.info("WorldEdit for Sponge (version " + getInternalVersion() + ") is loaded"); - } - - @Listener - public void serverAboutToStart(GameAboutToStartServerEvent event) { if (this.platform != null) { - logger.warn("GameAboutToStartServerEvent occurred when GameStoppingServerEvent hasn't"); + logger.warn("StartingEngineEvent occurred when StoppingEngineEvent hasn't"); WorldEdit.getInstance().getPlatformManager().unregister(platform); } - final Path delChunks = workingDir.toPath().resolve(DELCHUNKS_FILE_NAME); + final Path delChunks = workingDir.resolve(DELCHUNKS_FILE_NAME); if (Files.exists(delChunks)) { ChunkDeleter.runFromFile(delChunks, true); } @@ -150,76 +131,66 @@ public void serverAboutToStart(GameAboutToStartServerEvent event) { this.platform = new SpongePlatform(this); this.provider = new SpongePermissionsProvider(); - for (BlockType blockType : Sponge.getRegistry().getAllOf(BlockType.class)) { - // TODO Handle blockstate stuff - String id = blockType.getId(); + WorldEdit.getInstance().getPlatformManager().register(platform); + } + + @Listener + public void serverStarting(StartingEngineEvent event) { + RegistryTypes.BLOCK_TYPE.get().streamEntries().forEach(registryEntry -> { + String id = registryEntry.key().getFormatted(); if (!com.sk89q.worldedit.world.block.BlockType.REGISTRY.keySet().contains(id)) { - com.sk89q.worldedit.world.block.BlockType.REGISTRY.register(id, new com.sk89q.worldedit.world.block.BlockType(id)); + com.sk89q.worldedit.world.block.BlockType.REGISTRY.register( + id, + new com.sk89q.worldedit.world.block.BlockType(id, + blockState -> SpongeAdapter.adapt(SpongeAdapter.adapt(blockState.getBlockType()).getDefaultState())) + ); } - } + }); - for (ItemType itemType : Sponge.getRegistry().getAllOf(ItemType.class)) { - String id = itemType.getId(); + RegistryTypes.ITEM_TYPE.get().streamEntries().forEach(registryEntry -> { + String id = registryEntry.key().getFormatted(); if (!com.sk89q.worldedit.world.item.ItemType.REGISTRY.keySet().contains(id)) { com.sk89q.worldedit.world.item.ItemType.REGISTRY.register(id, new com.sk89q.worldedit.world.item.ItemType(id)); } - } + }); - WorldEdit.getInstance().getPlatformManager().register(platform); + logger.info("WorldEdit for Sponge (version " + getInternalVersion() + ") is loaded"); } @Listener - public void serverStopping(GameStoppingServerEvent event) { + public void serverStopping(StoppingEngineEvent event) { WorldEdit worldEdit = WorldEdit.getInstance(); worldEdit.getSessionManager().unload(); worldEdit.getPlatformManager().unregister(platform); } @Listener - public void serverStarted(GameStartedServerEvent event) { + public void serverStarted(StartedEngineEvent event) { WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent()); - - loadAdapter(); } - private void loadAdapter() { - WorldEdit worldEdit = WorldEdit.getInstance(); - - // Attempt to load a Sponge adapter - SpongeImplLoader adapterLoader = new SpongeImplLoader(); + @Listener + public void onRegisterChannel(RegisterChannelEvent event) { + CUIChannelHandler.init(event); + } - try { - adapterLoader.addFromPath(getClass().getClassLoader()); - } catch (IOException e) { - logger.warn("Failed to search path for Sponge adapters"); - } + @Listener + public void onRegisterSpongeCommand(final RegisterCommandEvent event) { + platform.setCommandRegisterEvent(event); + platform.registerCommands(WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getCommandManager()); + platform.setCommandRegisterEvent(null); + } - try { - adapterLoader.addFromJar(container.getSource().get().toFile()); - } catch (IOException e) { - logger.warn("Failed to search " + container.getSource().get().toFile() + " for Sponge adapters", e); - } - try { - spongeAdapter = adapterLoader.loadAdapter(); - logger.info("Using " + spongeAdapter.getClass().getCanonicalName() + " as the Sponge adapter"); - } catch (AdapterLoadException e) { - Platform platform = worldEdit.getPlatformManager().queryCapability(Capability.WORLD_EDITING); - if (platform instanceof SpongePlatform) { - logger.warn(e.getMessage()); - } else { - logger.info("WorldEdit could not find a Sponge adapter for this MC version, " - + "but it seems that you have another implementation of WorldEdit installed (" + platform.getPlatformName() + ") " - + "that handles the world editing."); - } - } + public PluginContainer getContainer() { + return this.container; } - public SpongeImplAdapter getAdapter() { - return this.spongeAdapter; + public Logger getLogger() { + return this.logger; } @Listener - public void onPlayerItemInteract(InteractItemEvent.Secondary event, @Root Player spongePlayer) { + public void onPlayerItemInteract(InteractItemEvent.Secondary event, @Root ServerPlayer spongePlayer) { if (platform == null) { return; } @@ -237,7 +208,7 @@ public void onPlayerItemInteract(InteractItemEvent.Secondary event, @Root Player } @Listener - public void onPlayerInteract(InteractBlockEvent event, @Root Player spongePlayer) { + public void onPlayerInteract(InteractBlockEvent event, @Root ServerPlayer spongePlayer) { if (platform == null) { return; } @@ -251,59 +222,51 @@ public void onPlayerInteract(InteractBlockEvent event, @Root Player spongePlayer SpongePlayer player = wrapPlayer(spongePlayer); com.sk89q.worldedit.world.World world = player.getWorld(); - BlockSnapshot targetBlock = event.getTargetBlock(); - Optional> optLoc = targetBlock.getLocation(); + BlockSnapshot targetBlock = event.getBlock(); + Optional optLoc = targetBlock.getLocation(); BlockType interactedType = targetBlock.getState().getType(); - if (event instanceof InteractBlockEvent.Primary) { - if (interactedType != BlockTypes.AIR) { + if (event instanceof InteractBlockEvent.Primary.Start) { + if (interactedType != BlockTypes.AIR.get()) { if (!optLoc.isPresent()) { return; } - Location loc = optLoc.get(); + ServerLocation loc = optLoc.get(); com.sk89q.worldedit.util.Location pos = new com.sk89q.worldedit.util.Location( world, loc.getX(), loc.getY(), loc.getZ()); if (we.handleBlockLeftClick(player, pos)) { - event.setCancelled(true); + ((InteractBlockEvent.Primary.Start) event).setCancelled(true); } - if (we.handleArmSwing(player)) { - event.setCancelled(true); - } - } else { - if (we.handleArmSwing(player)) { - event.setCancelled(true); - } + } + if (we.handleArmSwing(player)) { + ((InteractBlockEvent.Primary.Start) event).setCancelled(true); } } else if (event instanceof InteractBlockEvent.Secondary) { if (!optLoc.isPresent()) { return; } - Location loc = optLoc.get(); + ServerLocation loc = optLoc.get(); com.sk89q.worldedit.util.Location pos = new com.sk89q.worldedit.util.Location( world, loc.getX(), loc.getY(), loc.getZ()); if (we.handleBlockRightClick(player, pos)) { - event.setCancelled(true); + ((InteractBlockEvent.Secondary) event).setCancelled(true); } if (we.handleRightClick(player)) { - event.setCancelled(true); + ((InteractBlockEvent.Secondary) event).setCancelled(true); } } } @Listener - public void onPlayerQuit(ClientConnectionEvent.Disconnect event) { + public void onPlayerQuit(ServerSideConnectionEvent.Disconnect event) { WorldEdit.getInstance().getEventBus() - .post(new SessionIdleEvent(new SpongePlayer.SessionKeyImpl(event.getTargetEntity()))); - } - - public static ItemStack toSpongeItemStack(BaseItemStack item) { - return inst().getAdapter().makeSpongeStack(item); + .post(new SessionIdleEvent(new SpongePlayer.SessionKeyImpl(event.getPlayer()))); } /** @@ -321,17 +284,21 @@ SpongeConfiguration getConfig() { * @param player the player * @return the WorldEdit player */ - public SpongePlayer wrapPlayer(Player player) { + public SpongePlayer wrapPlayer(ServerPlayer player) { checkNotNull(player); return new SpongePlayer(platform, player); } - public Actor wrapCommandSource(CommandSource sender) { - if (sender instanceof Player) { - return wrapPlayer((Player) sender); + public Actor wrapCommandCause(CommandCause cause) { + Object rootCause = cause.getCause().root(); + if (rootCause instanceof ServerPlayer) { + return wrapPlayer((ServerPlayer) rootCause); } - - return new SpongeCommandSender(this, sender); + if (rootCause instanceof Audience) { + return new SpongeCommandSender(this, (Audience) rootCause); + } + // TODO CommandBlocks + return null; } /** @@ -340,22 +307,11 @@ public Actor wrapCommandSource(CommandSource sender) { * @param player the player * @return the session */ - public LocalSession getSession(Player player) { + public LocalSession getSession(ServerPlayer player) { checkNotNull(player); return WorldEdit.getInstance().getSessionManager().get(wrapPlayer(player)); } - /** - * Get the WorldEdit proxy for the given world. - * - * @param world the world - * @return the WorldEdit world - */ - public SpongeWorld getWorld(World world) { - checkNotNull(world); - return getAdapter().getWorld(world); - } - /** * Get the WorldEdit proxy for the platform. * @@ -371,7 +327,7 @@ public Platform getPlatform() { * @return the working directory */ public Path getWorkingDir() { - return this.workingDir.toPath(); + return this.workingDir; } /** @@ -380,7 +336,7 @@ public Path getWorkingDir() { * @return a version string */ String getInternalVersion() { - return container.getVersion().orElse("Unknown"); + return container.getMetadata().getVersion(); } public void setPermissionsProvider(SpongePermissionsProvider provider) { diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplAdapter.java deleted file mode 100644 index fcb2dc333a..0000000000 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplAdapter.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * 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 com.sk89q.worldedit.sponge.adapter; - -import com.flowpowered.math.vector.Vector3d; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.sponge.SpongeWorld; -import com.sk89q.worldedit.util.Location; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.item.inventory.ItemStack; -import org.spongepowered.api.world.World; - -/** - * An interface for various things that can't be done through the Sponge API. - */ -public interface SpongeImplAdapter { - - BaseEntity createBaseEntity(Entity entity); - - ItemStack makeSpongeStack(BaseItemStack itemStack); - - SpongeWorld getWorld(World world); - - default boolean isBest() { - return true; - } - - default Location adapt(org.spongepowered.api.world.Location loc, Vector3d rot) { - Vector3 position = Vector3.at(loc.getX(), loc.getY(), loc.getZ()); - - return new Location(getWorld(loc.getExtent()), position, (float) rot.getY(), (float) rot.getX()); - } -} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplLoader.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplLoader.java deleted file mode 100644 index 9b8e377566..0000000000 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/SpongeImplLoader.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * 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 com.sk89q.worldedit.sponge.adapter; - -import com.google.common.collect.Lists; -import com.sk89q.worldedit.util.io.Closer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -/** - * Loads Sponge implementation adapters. - */ -public class SpongeImplLoader { - - private static final Logger log = LoggerFactory.getLogger(SpongeImplLoader.class); - private final List adapterCandidates = new ArrayList<>(); - private String customCandidate; - - private static final String SEARCH_PACKAGE = "com.sk89q.worldedit.sponge.adapter.impl"; - private static final String SEARCH_PACKAGE_DOT = SEARCH_PACKAGE + "."; - private static final String SEARCH_PATH = SEARCH_PACKAGE.replace(".", "/"); - private static final String CLASS_SUFFIX = ".class"; - - private static final String LOAD_ERROR_MESSAGE = - "\n**********************************************\n" - + "** This WorldEdit version does not support your version of Sponge.\n" - + "** WorldEdit will not function! \n" - + "** \n" - + "** Please ensure you are running the latest version\n" - + "**********************************************\n"; - - /** - * Create a new instance. - */ - public SpongeImplLoader() { - addDefaults(); - } - - /** - * Add default candidates, such as any defined with - * {@code -Dworldedit.sponge.adapter}. - */ - private void addDefaults() { - String className = System.getProperty("worldedit.sponge.adapter"); - if (className != null) { - customCandidate = className; - adapterCandidates.add(className); - log.info("-Dworldedit.sponge.adapter used to add " + className + " to the list of available Sponge adapters"); - } - } - - /** - * Search the given JAR for candidate implementations. - * - * @param file the file - * @throws IOException thrown on I/O error - */ - public void addFromJar(File file) throws IOException { - Closer closer = Closer.create(); - JarFile jar = closer.register(new JarFile(file)); - try { - Enumeration entries = jar.entries(); - while (entries.hasMoreElements()) { - JarEntry jarEntry = (JarEntry) entries.nextElement(); - - String className = jarEntry.getName().replaceAll("[/\\\\]+", "."); - - if (!className.startsWith(SEARCH_PACKAGE_DOT) || jarEntry.isDirectory() || className.contains("$")) { - continue; - } - - int beginIndex = 0; - int endIndex = className.length() - CLASS_SUFFIX.length(); - className = className.substring(beginIndex, endIndex); - adapterCandidates.add(className); - } - } finally { - closer.close(); - } - } - - /** - * Search for classes stored as separate files available via the given - * class loader. - * - * @param classLoader the class loader - * @throws IOException thrown on error - */ - public void addFromPath(ClassLoader classLoader) throws IOException { - Enumeration resources = classLoader.getResources(SEARCH_PATH); - while (resources.hasMoreElements()) { - File file = new File(resources.nextElement().getFile()); - addFromPath(file); - } - } - - /** - * Search for classes stored as separate files available via the given - * path. - * - * @param file the path - */ - private void addFromPath(File file) { - String resource = SEARCH_PACKAGE_DOT + file.getName(); - if (file.isDirectory()) { - File[] files = file.listFiles(); - if (files != null) { - for (File child : files) { - addFromPath(child); - } - } - } else if (resource.endsWith(CLASS_SUFFIX)) { - int beginIndex = 0; - int endIndex = resource.length() - CLASS_SUFFIX.length(); - String className = resource.substring(beginIndex, endIndex); - if (!className.contains("$")) { - adapterCandidates.add(className); - } - } - } - - /** - * Iterate through the list of candidates and load an adapter. - * - * @return an adapter - * @throws AdapterLoadException thrown if no adapter could be found - */ - public SpongeImplAdapter loadAdapter() throws AdapterLoadException { - List suitableAdapters = Lists.newArrayList(); - for (String className : adapterCandidates) { - try { - Class cls = Class.forName(className); - if (SpongeImplAdapter.class.isAssignableFrom(cls)) { - suitableAdapters.add((SpongeImplAdapter) cls.newInstance()); - } else { - log.warn("Failed to load the Sponge adapter class '" + className - + "' because it does not implement " + SpongeImplAdapter.class.getCanonicalName()); - } - } catch (ClassNotFoundException e) { - log.warn("Failed to load the Sponge adapter class '" + className - + "' that is not supposed to be missing", e); - } catch (IllegalAccessException e) { - log.warn("Failed to load the Sponge adapter class '" + className - + "' that is not supposed to be raising this error", e); - } catch (Throwable e) { - if (className.equals(customCandidate)) { - log.warn("Failed to load the Sponge adapter class '" + className + "'", e); - } - } - } - - if (suitableAdapters.isEmpty()) { - throw new AdapterLoadException(LOAD_ERROR_MESSAGE); - } else { - if (suitableAdapters.size() == 1) { - return suitableAdapters.get(0); - } else { - return suitableAdapters.stream().sorted((o1, o2) -> { - if (o1.isBest() && !o2.isBest()) { - return -1; - } else if (!o1.isBest() && o2.isBest()) { - return 1; - } - return 0; - }).findFirst().orElse(suitableAdapters.get(0)); - } - } - } -} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/config/ConfigurateConfiguration.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/config/ConfigurateConfiguration.java index b5cdd330fa..734ff049f8 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/config/ConfigurateConfiguration.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/config/ConfigurateConfiguration.java @@ -19,17 +19,17 @@ package com.sk89q.worldedit.sponge.config; -import com.google.common.reflect.TypeToken; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.session.SessionManager; import com.sk89q.worldedit.util.report.Unreported; import com.sk89q.worldedit.world.registry.LegacyMapper; -import ninja.leaping.configurate.ConfigurationOptions; -import ninja.leaping.configurate.commented.CommentedConfigurationNode; -import ninja.leaping.configurate.loader.ConfigurationLoader; -import ninja.leaping.configurate.objectmapping.ObjectMappingException; +import io.leangen.geantyref.TypeToken; import org.slf4j.Logger; +import org.spongepowered.configurate.CommentedConfigurationNode; +import org.spongepowered.configurate.ConfigurationOptions; +import org.spongepowered.configurate.loader.ConfigurationLoader; +import org.spongepowered.configurate.serialize.SerializationException; import java.io.IOException; import java.util.HashSet; @@ -51,87 +51,87 @@ public ConfigurateConfiguration(ConfigurationLoader public void load() { try { ConfigurationOptions options = ConfigurationOptions.defaults(); - options = options.setShouldCopyDefaults(true); + options = options.shouldCopyDefaults(true); node = config.load(options); } catch (IOException e) { logger.warn("Error loading WorldEdit configuration", e); } - profile = node.getNode("debug").getBoolean(profile); - traceUnflushedSessions = node.getNode("debugging", "trace-unflushed-sessions").getBoolean(traceUnflushedSessions); - wandItem = node.getNode("wand-item").getString(wandItem).toLowerCase(Locale.ROOT); + profile = node.node("debug").getBoolean(profile); + traceUnflushedSessions = node.node("debugging", "trace-unflushed-sessions").getBoolean(traceUnflushedSessions); + wandItem = node.node("wand-item").getString(wandItem).toLowerCase(Locale.ROOT); try { wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId(); } catch (Throwable ignored) { } - defaultChangeLimit = Math.max(-1, node.getNode("limits", "max-blocks-changed", "default").getInt(defaultChangeLimit)); - maxChangeLimit = Math.max(-1, node.getNode("limits", "max-blocks-changed", "maximum").getInt(maxChangeLimit)); + defaultChangeLimit = Math.max(-1, node.node("limits", "max-blocks-changed", "default").getInt(defaultChangeLimit)); + maxChangeLimit = Math.max(-1, node.node("limits", "max-blocks-changed", "maximum").getInt(maxChangeLimit)); - defaultVerticalHeight = Math.max(1, node.getNode("limits", "vertical-height", "default").getInt(defaultVerticalHeight)); + defaultVerticalHeight = Math.max(1, node.node("limits", "vertical-height", "default").getInt(defaultVerticalHeight)); - defaultMaxPolygonalPoints = Math.max(-1, node.getNode("limits", "max-polygonal-points", "default").getInt(defaultMaxPolygonalPoints)); - maxPolygonalPoints = Math.max(-1, node.getNode("limits", "max-polygonal-points", "maximum").getInt(maxPolygonalPoints)); + defaultMaxPolygonalPoints = Math.max(-1, node.node("limits", "max-polygonal-points", "default").getInt(defaultMaxPolygonalPoints)); + maxPolygonalPoints = Math.max(-1, node.node("limits", "max-polygonal-points", "maximum").getInt(maxPolygonalPoints)); - maxRadius = Math.max(-1, node.getNode("limits", "max-radius").getInt(maxRadius)); - maxBrushRadius = node.getNode("limits", "max-brush-radius").getInt(maxBrushRadius); - maxSuperPickaxeSize = Math.max(1, node.getNode("limits", "max-super-pickaxe-size").getInt(maxSuperPickaxeSize)); + maxRadius = Math.max(-1, node.node("limits", "max-radius").getInt(maxRadius)); + maxBrushRadius = node.node("limits", "max-brush-radius").getInt(maxBrushRadius); + maxSuperPickaxeSize = Math.max(1, node.node("limits", "max-super-pickaxe-size").getInt(maxSuperPickaxeSize)); - butcherDefaultRadius = Math.max(-1, node.getNode("limits", "butcher-radius", "default").getInt(butcherDefaultRadius)); - butcherMaxRadius = Math.max(-1, node.getNode("limits", "butcher-radius", "maximum").getInt(butcherMaxRadius)); + butcherDefaultRadius = Math.max(-1, node.node("limits", "butcher-radius", "default").getInt(butcherDefaultRadius)); + butcherMaxRadius = Math.max(-1, node.node("limits", "butcher-radius", "maximum").getInt(butcherMaxRadius)); try { - disallowedBlocks = new HashSet<>(node.getNode("limits", "disallowed-blocks").getList(TypeToken.of(String.class))); - } catch (ObjectMappingException e) { + disallowedBlocks = new HashSet<>(node.node("limits", "disallowed-blocks").getList(TypeToken.get(String.class))); + } catch (SerializationException e) { logger.warn("Error loading WorldEdit configuration", e); } try { - allowedDataCycleBlocks = new HashSet<>(node.getNode("limits", "allowed-data-cycle-blocks").getList(TypeToken.of(String.class))); - } catch (ObjectMappingException e) { + allowedDataCycleBlocks = new HashSet<>(node.node("limits", "allowed-data-cycle-blocks").getList(TypeToken.get(String.class))); + } catch (SerializationException e) { logger.warn("Error loading WorldEdit configuration", e); } - registerHelp = node.getNode("register-help").getBoolean(true); - logCommands = node.getNode("logging", "log-commands").getBoolean(logCommands); - logFile = node.getNode("logging", "file").getString(logFile); - logFormat = node.getNode("logging", "format").getString(logFormat); + registerHelp = node.node("register-help").getBoolean(true); + logCommands = node.node("logging", "log-commands").getBoolean(logCommands); + logFile = node.node("logging", "file").getString(logFile); + logFormat = node.node("logging", "format").getString(logFormat); - superPickaxeDrop = node.getNode("super-pickaxe", "drop-items").getBoolean(superPickaxeDrop); - superPickaxeManyDrop = node.getNode("super-pickaxe", "many-drop-items").getBoolean(superPickaxeManyDrop); + superPickaxeDrop = node.node("super-pickaxe", "drop-items").getBoolean(superPickaxeDrop); + superPickaxeManyDrop = node.node("super-pickaxe", "many-drop-items").getBoolean(superPickaxeManyDrop); - useInventory = node.getNode("use-inventory", "enable").getBoolean(useInventory); - useInventoryOverride = node.getNode("use-inventory", "allow-override").getBoolean(useInventoryOverride); - useInventoryCreativeOverride = node.getNode("use-inventory", "creative-mode-overrides").getBoolean(useInventoryCreativeOverride); + useInventory = node.node("use-inventory", "enable").getBoolean(useInventory); + useInventoryOverride = node.node("use-inventory", "allow-override").getBoolean(useInventoryOverride); + useInventoryCreativeOverride = node.node("use-inventory", "creative-mode-overrides").getBoolean(useInventoryCreativeOverride); - navigationWand = node.getNode("navigation-wand", "item").getString(navigationWand).toLowerCase(Locale.ROOT); + navigationWand = node.node("navigation-wand", "item").getString(navigationWand).toLowerCase(Locale.ROOT); try { navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId(); } catch (Throwable ignored) { } - navigationWandMaxDistance = node.getNode("navigation-wand", "max-distance").getInt(navigationWandMaxDistance); - navigationUseGlass = node.getNode("navigation", "use-glass").getBoolean(navigationUseGlass); + navigationWandMaxDistance = node.node("navigation-wand", "max-distance").getInt(navigationWandMaxDistance); + navigationUseGlass = node.node("navigation", "use-glass").getBoolean(navigationUseGlass); - scriptTimeout = node.getNode("scripting", "timeout").getInt(scriptTimeout); - scriptsDir = node.getNode("scripting", "dir").getString(scriptsDir); + scriptTimeout = node.node("scripting", "timeout").getInt(scriptTimeout); + scriptsDir = node.node("scripting", "dir").getString(scriptsDir); - saveDir = node.getNode("saving", "dir").getString(saveDir); + saveDir = node.node("saving", "dir").getString(saveDir); - allowSymlinks = node.getNode("files", "allow-symbolic-links").getBoolean(false); - LocalSession.MAX_HISTORY_SIZE = Math.max(0, node.getNode("history", "size").getInt(15)); - SessionManager.EXPIRATION_GRACE = node.getNode("history", "expiration").getInt(10) * 60 * 1000; + allowSymlinks = node.node("files", "allow-symbolic-links").getBoolean(false); + LocalSession.MAX_HISTORY_SIZE = Math.max(0, node.node("history", "size").getInt(15)); + SessionManager.EXPIRATION_GRACE = node.node("history", "expiration").getInt(10) * 60 * 1000; - showHelpInfo = node.getNode("show-help-on-first-use").getBoolean(true); - serverSideCUI = node.getNode("server-side-cui").getBoolean(true); + showHelpInfo = node.node("show-help-on-first-use").getBoolean(true); + serverSideCUI = node.node("server-side-cui").getBoolean(true); - String snapshotsDir = node.getNode("snapshots", "directory").getString(""); - boolean experimentalSnapshots = node.getNode("snapshots", "experimental").getBoolean(false); + String snapshotsDir = node.node("snapshots", "directory").getString(""); + boolean experimentalSnapshots = node.node("snapshots", "experimental").getBoolean(false); initializeSnapshotConfiguration(snapshotsDir, experimentalSnapshots); - String type = node.getNode("shell-save-type").getString("").trim(); + String type = node.node("shell-save-type").getString("").trim(); shellSaveType = type.equals("") ? null : type; - extendedYLimit = node.getNode("compat", "extended-y-limit").getBoolean(false); - setDefaultLocaleName(node.getNode("default-locale").getString(defaultLocaleName)); + extendedYLimit = node.node("compat", "extended-y-limit").getBoolean(false); + setDefaultLocaleName(node.node("default-locale").getString(defaultLocaleName)); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/config/SpongeConfiguration.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/config/SpongeConfiguration.java index 333575b32a..fe46aefb77 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/config/SpongeConfiguration.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/config/SpongeConfiguration.java @@ -21,10 +21,9 @@ import com.google.inject.Inject; import com.sk89q.worldedit.sponge.SpongeWorldEdit; -import ninja.leaping.configurate.commented.CommentedConfigurationNode; -import ninja.leaping.configurate.loader.ConfigurationLoader; -import org.slf4j.Logger; import org.spongepowered.api.config.DefaultConfig; +import org.spongepowered.configurate.CommentedConfigurationNode; +import org.spongepowered.configurate.loader.ConfigurationLoader; import java.io.IOException; import java.nio.file.Path; @@ -35,16 +34,16 @@ public class SpongeConfiguration extends ConfigurateConfiguration { public boolean cheatMode = false; @Inject - public SpongeConfiguration(@DefaultConfig(sharedRoot = false) ConfigurationLoader config, Logger logger) { - super(config, logger); + public SpongeConfiguration(@DefaultConfig(sharedRoot = false) ConfigurationLoader config) { + super(config, SpongeWorldEdit.inst().getLogger()); } @Override public void load() { super.load(); - creativeEnable = node.getNode("use-in-creative").getBoolean(false); - cheatMode = node.getNode("cheat-mode").getBoolean(false); + creativeEnable = node.node("use-in-creative").getBoolean(false); + cheatMode = node.node("cheat-mode").getBoolean(false); try { config.save(node); diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/internal/NBTConverter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/internal/NBTConverter.java new file mode 100644 index 0000000000..2aca943176 --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/internal/NBTConverter.java @@ -0,0 +1,258 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * 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 com.sk89q.worldedit.sponge.internal; + +import com.sk89q.worldedit.util.nbt.BinaryTag; +import com.sk89q.worldedit.util.nbt.ByteArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.ByteBinaryTag; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import com.sk89q.worldedit.util.nbt.DoubleBinaryTag; +import com.sk89q.worldedit.util.nbt.EndBinaryTag; +import com.sk89q.worldedit.util.nbt.FloatBinaryTag; +import com.sk89q.worldedit.util.nbt.IntArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.IntBinaryTag; +import com.sk89q.worldedit.util.nbt.ListBinaryTag; +import com.sk89q.worldedit.util.nbt.LongArrayBinaryTag; +import com.sk89q.worldedit.util.nbt.LongBinaryTag; +import com.sk89q.worldedit.util.nbt.ShortBinaryTag; +import com.sk89q.worldedit.util.nbt.StringBinaryTag; + +import java.util.Arrays; +import java.util.Set; + +/** + * Converts between JNBT and Minecraft NBT classes. + */ +public final class NBTConverter { + + private NBTConverter() { + } + + public static net.minecraft.nbt.Tag toNative(BinaryTag tag) { + if (tag instanceof IntArrayBinaryTag) { + return toNative((IntArrayBinaryTag) tag); + + } else if (tag instanceof ListBinaryTag) { + return toNative((ListBinaryTag) tag); + + } else if (tag instanceof LongBinaryTag) { + return toNative((LongBinaryTag) tag); + + } else if (tag instanceof LongArrayBinaryTag) { + return toNative((LongArrayBinaryTag) tag); + + } else if (tag instanceof StringBinaryTag) { + return toNative((StringBinaryTag) tag); + + } else if (tag instanceof IntBinaryTag) { + return toNative((IntBinaryTag) tag); + + } else if (tag instanceof ByteBinaryTag) { + return toNative((ByteBinaryTag) tag); + + } else if (tag instanceof ByteArrayBinaryTag) { + return toNative((ByteArrayBinaryTag) tag); + + } else if (tag instanceof CompoundBinaryTag) { + return toNative((CompoundBinaryTag) tag); + + } else if (tag instanceof FloatBinaryTag) { + return toNative((FloatBinaryTag) tag); + + } else if (tag instanceof ShortBinaryTag) { + return toNative((ShortBinaryTag) tag); + + } else if (tag instanceof DoubleBinaryTag) { + return toNative((DoubleBinaryTag) tag); + } else { + throw new IllegalArgumentException("Can't convert tag of type " + tag.getClass().getCanonicalName()); + } + } + + public static net.minecraft.nbt.IntArrayTag toNative(IntArrayBinaryTag tag) { + int[] value = tag.value(); + return new net.minecraft.nbt.IntArrayTag(Arrays.copyOf(value, value.length)); + } + + public static net.minecraft.nbt.ListTag toNative(ListBinaryTag tag) { + net.minecraft.nbt.ListTag list = new net.minecraft.nbt.ListTag(); + for (BinaryTag child : tag) { + if (child instanceof EndBinaryTag) { + continue; + } + list.add(toNative(child)); + } + return list; + } + + public static net.minecraft.nbt.LongTag toNative(LongBinaryTag tag) { + return net.minecraft.nbt.LongTag.valueOf(tag.value()); + } + + public static net.minecraft.nbt.LongArrayTag toNative(LongArrayBinaryTag tag) { + return new net.minecraft.nbt.LongArrayTag(tag.value().clone()); + } + + public static net.minecraft.nbt.StringTag toNative(StringBinaryTag tag) { + return net.minecraft.nbt.StringTag.valueOf(tag.value()); + } + + public static net.minecraft.nbt.IntTag toNative(IntBinaryTag tag) { + return net.minecraft.nbt.IntTag.valueOf(tag.value()); + } + + public static net.minecraft.nbt.ByteTag toNative(ByteBinaryTag tag) { + return net.minecraft.nbt.ByteTag.valueOf(tag.value()); + } + + public static net.minecraft.nbt.ByteArrayTag toNative(ByteArrayBinaryTag tag) { + return new net.minecraft.nbt.ByteArrayTag(tag.value().clone()); + } + + public static net.minecraft.nbt.CompoundTag toNative(CompoundBinaryTag tag) { + net.minecraft.nbt.CompoundTag compound = new net.minecraft.nbt.CompoundTag(); + for (String key : tag.keySet()) { + compound.put(key, toNative(tag.get(key))); + } + return compound; + } + + public static net.minecraft.nbt.FloatTag toNative(FloatBinaryTag tag) { + return net.minecraft.nbt.FloatTag.valueOf(tag.value()); + } + + public static net.minecraft.nbt.ShortTag toNative(ShortBinaryTag tag) { + return net.minecraft.nbt.ShortTag.valueOf(tag.value()); + } + + public static net.minecraft.nbt.DoubleTag toNative(DoubleBinaryTag tag) { + return net.minecraft.nbt.DoubleTag.valueOf(tag.value()); + } + + public static BinaryTag fromNative(net.minecraft.nbt.Tag other) { + if (other instanceof net.minecraft.nbt.IntArrayTag) { + return fromNative((net.minecraft.nbt.IntArrayTag) other); + + } else if (other instanceof net.minecraft.nbt.ListTag) { + return fromNative((net.minecraft.nbt.ListTag) other); + + } else if (other instanceof net.minecraft.nbt.EndTag) { + return fromNative((net.minecraft.nbt.EndTag) other); + + } else if (other instanceof net.minecraft.nbt.LongTag) { + return fromNative((net.minecraft.nbt.LongTag) other); + + } else if (other instanceof net.minecraft.nbt.LongArrayTag) { + return fromNative((net.minecraft.nbt.LongArrayTag) other); + + } else if (other instanceof net.minecraft.nbt.StringTag) { + return fromNative((net.minecraft.nbt.StringTag) other); + + } else if (other instanceof net.minecraft.nbt.IntTag) { + return fromNative((net.minecraft.nbt.IntTag) other); + + } else if (other instanceof net.minecraft.nbt.ByteTag) { + return fromNative((net.minecraft.nbt.ByteTag) other); + + } else if (other instanceof net.minecraft.nbt.ByteArrayTag) { + return fromNative((net.minecraft.nbt.ByteArrayTag) other); + + } else if (other instanceof net.minecraft.nbt.CompoundTag) { + return fromNative((net.minecraft.nbt.CompoundTag) other); + + } else if (other instanceof net.minecraft.nbt.FloatTag) { + return fromNative((net.minecraft.nbt.FloatTag) other); + + } else if (other instanceof net.minecraft.nbt.ShortTag) { + return fromNative((net.minecraft.nbt.ShortTag) other); + + } else if (other instanceof net.minecraft.nbt.DoubleTag) { + return fromNative((net.minecraft.nbt.DoubleTag) other); + } else { + throw new IllegalArgumentException("Can't convert other of type " + other.getClass().getCanonicalName()); + } + } + + public static IntArrayBinaryTag fromNative(net.minecraft.nbt.IntArrayTag other) { + int[] value = other.getAsIntArray(); + return IntArrayBinaryTag.of(Arrays.copyOf(value, value.length)); + } + + public static ListBinaryTag fromNative(net.minecraft.nbt.ListTag other) { + other = other.copy(); + ListBinaryTag.Builder list = ListBinaryTag.builder(); + int tags = other.size(); + for (int i = 0; i < tags; i++) { + BinaryTag child = fromNative(other.remove(0)); + list.add(child); + } + return list.build(); + } + + public static EndBinaryTag fromNative(net.minecraft.nbt.EndTag other) { + return EndBinaryTag.get(); + } + + public static LongBinaryTag fromNative(net.minecraft.nbt.LongTag other) { + return LongBinaryTag.of(other.getAsLong()); + } + + public static LongArrayBinaryTag fromNative(net.minecraft.nbt.LongArrayTag other) { + return LongArrayBinaryTag.of(other.getAsLongArray().clone()); + } + + public static StringBinaryTag fromNative(net.minecraft.nbt.StringTag other) { + return StringBinaryTag.of(other.getAsString()); + } + + public static IntBinaryTag fromNative(net.minecraft.nbt.IntTag other) { + return IntBinaryTag.of(other.getAsInt()); + } + + public static ByteBinaryTag fromNative(net.minecraft.nbt.ByteTag other) { + return ByteBinaryTag.of(other.getAsByte()); + } + + public static ByteArrayBinaryTag fromNative(net.minecraft.nbt.ByteArrayTag other) { + return ByteArrayBinaryTag.of(other.getAsByteArray().clone()); + } + + public static CompoundBinaryTag fromNative(net.minecraft.nbt.CompoundTag other) { + Set tags = other.getAllKeys(); + CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder(); + for (String tagName : tags) { + builder.put(tagName, fromNative(other.get(tagName))); + } + return builder.build(); + } + + public static FloatBinaryTag fromNative(net.minecraft.nbt.FloatTag other) { + return FloatBinaryTag.of(other.getAsFloat()); + } + + public static ShortBinaryTag fromNative(net.minecraft.nbt.ShortTag other) { + return ShortBinaryTag.of(other.getAsShort()); + } + + public static DoubleBinaryTag fromNative(net.minecraft.nbt.DoubleTag other) { + return DoubleBinaryTag.of(other.getAsDouble()); + } + +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/internal/SpongeWorldNativeAccess.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/internal/SpongeWorldNativeAccess.java new file mode 100644 index 0000000000..031606821f --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/internal/SpongeWorldNativeAccess.java @@ -0,0 +1,153 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * 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 com.sk89q.worldedit.sponge.internal; + +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; + +import java.lang.ref.WeakReference; +import java.util.Objects; +import javax.annotation.Nullable; + +public class SpongeWorldNativeAccess implements WorldNativeAccess { + private static final int UPDATE = 1; + private static final int NOTIFY = 2; + + private final WeakReference world; + private SideEffectSet sideEffectSet; + + public SpongeWorldNativeAccess(WeakReference world) { + this.world = world; + } + + private Level getWorld() { + return Objects.requireNonNull(world.get(), "The reference to the world was lost"); + } + + @Override + public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + + @Override + public LevelChunk getChunk(int x, int z) { + return getWorld().getChunk(x, z); + } + + @Override + public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) { + int stateId = BlockStateIdAccess.getBlockStateId(state); + return BlockStateIdAccess.isValidInternalId(stateId) + ? Block.stateById(stateId) + : null; // TODO SpongeAdapter.adapt(state); + } + + @Override + public BlockState getBlockState(LevelChunk chunk, BlockPos position) { + return chunk.getBlockState(position); + } + + @Nullable + @Override + public BlockState setBlockState(LevelChunk chunk, BlockPos position, BlockState state) { + // TODO - We have access to mixins - do it here + // if (chunk instanceof ExtendedChunk) { + // return ((ExtendedChunk) chunk).setBlockState( + // position, state, false, sideEffectSet.shouldApply(SideEffect.UPDATE) + // ); + // } + return chunk.setBlockState(position, state, false); + } + + @Override + public BlockState getValidBlockForPosition(BlockState block, BlockPos position) { + return Block.updateFromNeighbourShapes(block, getWorld(), position); + } + + @Override + public BlockPos getPosition(int x, int y, int z) { + return new BlockPos(x, y, z); + } + + @Override + public void updateLightingForBlock(BlockPos position) { + getWorld().getChunkSource().getLightEngine().checkBlock(position); + } + + @Override + public boolean updateTileEntity(BlockPos position, CompoundBinaryTag tag) { + CompoundTag nativeTag = NBTConverter.toNative(tag); + BlockEntity tileEntity = getWorld().getChunk(position).getBlockEntity(position); + if (tileEntity == null) { + return false; + } + tileEntity.setLevelAndPosition(getWorld(), position); + tileEntity.load(getWorld().getBlockState(position), nativeTag); + return true; + } + + @Override + public void notifyBlockUpdate(BlockPos position, BlockState oldState, BlockState newState) { + getWorld().sendBlockUpdated(position, oldState, newState, UPDATE | NOTIFY); + } + + @Override + public boolean isChunkTicking(LevelChunk chunk) { + return chunk.getFullStatus().isOrAfter(ChunkHolder.FullChunkStatus.TICKING); + } + + @Override + public void markBlockChanged(BlockPos position) { + ((ServerChunkCache) getWorld().getChunkSource()).blockChanged(position); + } + + @Override + public void notifyNeighbors(BlockPos pos, BlockState oldState, BlockState newState) { + getWorld().updateNeighborsAt(pos, oldState.getBlock()); + if (newState.hasAnalogOutputSignal()) { + getWorld().updateNeighbourForOutputSignal(pos, newState.getBlock()); + } + } + + @Override + public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newState, int recursionLimit) { + Level world = getWorld(); + oldState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); + newState.updateNeighbourShapes(world, pos, NOTIFY, recursionLimit); + newState.updateIndirectNeighbourShapes(world, pos, NOTIFY, recursionLimit); + } + + @Override + public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { + getWorld().onBlockStateChange(pos, oldState, newState); + } +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBiomeRegistry.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBiomeRegistry.java similarity index 72% rename from worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBiomeRegistry.java rename to worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBiomeRegistry.java index fd012d2941..3f2414e2d5 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeBiomeRegistry.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBiomeRegistry.java @@ -17,14 +17,13 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.sponge; +package com.sk89q.worldedit.sponge.registry; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.translation.TranslationManager; import com.sk89q.worldedit.world.biome.BiomeData; import com.sk89q.worldedit.world.registry.BiomeRegistry; -import org.spongepowered.api.world.biome.BiomeType; import javax.annotation.Nullable; @@ -44,27 +43,6 @@ public Component getRichName(com.sk89q.worldedit.world.biome.BiomeType biomeType @Nullable @Override public BiomeData getData(com.sk89q.worldedit.world.biome.BiomeType biome) { - return new SpongeBiomeData(SpongeAdapter.adapt(biome)); + return null; } - - @Deprecated - private static class SpongeBiomeData implements BiomeData { - private final BiomeType biome; - - /** - * Create a new instance. - * - * @param biome the base biome - */ - private SpongeBiomeData(BiomeType biome) { - this.biome = biome; - } - - @SuppressWarnings("deprecation") - @Override - public String getName() { - return biome.getName(); - } - } - } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeRegistries.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBlockCategoryRegistry.java similarity index 56% rename from worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeRegistries.java rename to worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBlockCategoryRegistry.java index 47b83250e2..e026f51990 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeRegistries.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBlockCategoryRegistry.java @@ -17,31 +17,19 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.sponge; +package com.sk89q.worldedit.sponge.registry; -import com.sk89q.worldedit.world.registry.BiomeRegistry; -import com.sk89q.worldedit.world.registry.BundledRegistries; +import com.google.common.collect.ImmutableSet; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; -/** - * World data for the Sponge platform. - */ -class SpongeRegistries extends BundledRegistries { +import java.util.Set; - private static final SpongeRegistries INSTANCE = new SpongeRegistries(); - private final BiomeRegistry biomeRegistry = new SpongeBiomeRegistry(); +public class SpongeBlockCategoryRegistry implements BlockCategoryRegistry { @Override - public BiomeRegistry getBiomeRegistry() { - return biomeRegistry; - } - - /** - * Get a static instance. - * - * @return an instance - */ - public static SpongeRegistries getInstance() { - return INSTANCE; + public Set getCategorisedByName(String category) { + // TODO Sponge doesn't yet support tags + return ImmutableSet.of(); } - } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBlockRegistry.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBlockRegistry.java new file mode 100644 index 0000000000..d9966d0050 --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeBlockRegistry.java @@ -0,0 +1,64 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * 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 com.sk89q.worldedit.sponge.registry; + +import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.sponge.SpongeAdapter; +import com.sk89q.worldedit.sponge.SpongeTextAdapter; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.registry.BundledBlockRegistry; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.state.StateProperty; +import org.spongepowered.api.world.schematic.PaletteType; +import org.spongepowered.api.world.schematic.PaletteTypes; + +import java.util.Map; +import java.util.OptionalInt; +import java.util.TreeMap; +import javax.annotation.Nullable; + +public class SpongeBlockRegistry extends BundledBlockRegistry { + + @Override + public Component getRichName(BlockType blockType) { + return SpongeTextAdapter.convert(SpongeAdapter.adapt(blockType).asComponent()); + } + + @Nullable + @Override + public Map> getProperties(BlockType blockType) { + Map> map = new TreeMap<>(); + org.spongepowered.api.block.BlockType type = SpongeAdapter.adapt(blockType); + for (StateProperty stateProperty : type.getStateProperties()) { + map.put(stateProperty.getName(), SpongeAdapter.adaptProperty(stateProperty)); + } + return map; + } + + @Override + public OptionalInt getInternalBlockStateId(BlockState state) { + return PaletteTypes.BLOCK_STATE_PALETTE.get() + .create(Sponge.getGame().registries(), RegistryTypes.BLOCK_TYPE) + .get(SpongeAdapter.adapt(state)); + } +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/AdapterLoadException.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeItemCategoryRegistry.java similarity index 64% rename from worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/AdapterLoadException.java rename to worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeItemCategoryRegistry.java index f2698fc729..01e10f9756 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/adapter/AdapterLoadException.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeItemCategoryRegistry.java @@ -17,25 +17,19 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.sponge.adapter; +package com.sk89q.worldedit.sponge.registry; -/** - * Thrown when no adapter can be found. - */ -public class AdapterLoadException extends Exception { +import com.google.common.collect.ImmutableSet; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.registry.ItemCategoryRegistry; - public AdapterLoadException() { - } +import java.util.Set; - public AdapterLoadException(String message) { - super(message); - } - - public AdapterLoadException(String message, Throwable cause) { - super(message, cause); - } +public class SpongeItemCategoryRegistry implements ItemCategoryRegistry { - public AdapterLoadException(Throwable cause) { - super(cause); + @Override + public Set getCategorisedByName(String category) { + // TODO Sponge doesn't yet support tags + return ImmutableSet.of(); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeItemRegistry.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeItemRegistry.java new file mode 100644 index 0000000000..4a695d0c46 --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeItemRegistry.java @@ -0,0 +1,45 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * 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 com.sk89q.worldedit.sponge.registry; + +import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.sponge.SpongeAdapter; +import com.sk89q.worldedit.sponge.SpongeTextAdapter; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.registry.BundledItemRegistry; +import org.spongepowered.api.data.Keys; + +public class SpongeItemRegistry extends BundledItemRegistry { + + @Override + public Component getRichName(ItemType itemType) { + return SpongeTextAdapter.convert(SpongeAdapter.adapt(itemType).asComponent()); + } + + @Override + public Component getRichName(BaseItemStack itemStack) { + // return SpongeAdapter.adapt(itemStack).get(Keys.DISPLAY_NAME) + // .map(SpongeTextAdapter::convert) + // .orElseGet(() -> getRichName(itemStack.getType())); + return TextComponent.of("// TODO"); + } +} diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeRegistries.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeRegistries.java new file mode 100644 index 0000000000..b9107ee3d7 --- /dev/null +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/registry/SpongeRegistries.java @@ -0,0 +1,75 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * 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 com.sk89q.worldedit.sponge.registry; + +import com.sk89q.worldedit.world.registry.BiomeRegistry; +import com.sk89q.worldedit.world.registry.BlockCategoryRegistry; +import com.sk89q.worldedit.world.registry.BlockRegistry; +import com.sk89q.worldedit.world.registry.BundledRegistries; +import com.sk89q.worldedit.world.registry.ItemCategoryRegistry; +import com.sk89q.worldedit.world.registry.ItemRegistry; + +/** + * Registry data for the Sponge platform. + */ +public class SpongeRegistries extends BundledRegistries { + + private static final SpongeRegistries INSTANCE = new SpongeRegistries(); + private final BiomeRegistry biomeRegistry = new SpongeBiomeRegistry(); + private final BlockRegistry blockRegistry = new SpongeBlockRegistry(); + private final BlockCategoryRegistry blockCategoryRegistry = new SpongeBlockCategoryRegistry(); + private final ItemCategoryRegistry itemCategoryRegistry = new SpongeItemCategoryRegistry(); + private final ItemRegistry itemRegistry = new SpongeItemRegistry(); + + @Override + public BiomeRegistry getBiomeRegistry() { + return this.biomeRegistry; + } + + @Override + public BlockRegistry getBlockRegistry() { + return this.blockRegistry; + } + + @Override + public BlockCategoryRegistry getBlockCategoryRegistry() { + return this.blockCategoryRegistry; + } + + @Override + public ItemCategoryRegistry getItemCategoryRegistry() { + return this.itemCategoryRegistry; + } + + @Override + public ItemRegistry getItemRegistry() { + return this.itemRegistry; + } + + /** + * Get a static instance. + * + * @return an instance + */ + public static SpongeRegistries getInstance() { + return INSTANCE; + } + +} diff --git a/worldedit-sponge/src/main/resources/META-INF/plugins.json b/worldedit-sponge/src/main/resources/META-INF/plugins.json new file mode 100644 index 0000000000..3aa04fc6d7 --- /dev/null +++ b/worldedit-sponge/src/main/resources/META-INF/plugins.json @@ -0,0 +1,24 @@ +{ + "plugins": [ + { + "loader": "java_plain", + "id": "worldedit", + "name": "WorldEdit", + "version": "7.2.0-SNAPSHOT", + "main-class": "com.sk89q.worldedit.sponge.SpongeWorldEdit", + "description": "WorldEdit", + "links": { + "homepage": "https://www.spongepowered.org", + "source": "https://www.spongepowered.org/source", + "issues": "https://www.spongepowered.org/issues" + }, + "dependencies": [ + { + "id": "spongeapi", + "version": "8.0.0" + } + ], + "extra": {} + } + ] +} \ No newline at end of file