From 89e04ffb395d690cc521fba9e0305dcfcf8e502b Mon Sep 17 00:00:00 2001 From: Moulberry Date: Thu, 16 Nov 2023 19:20:28 +0800 Subject: [PATCH] WorldProperties: Rewrite API --- build.gradle.kts | 2 +- .../java/com/moulberry/axiom/AxiomPaper.java | 19 ++-- .../axiom/WorldPropertiesExample.java | 76 +++++++++------ .../AxiomCreateWorldPropertiesEvent.java | 3 +- .../axiom/packet/HelloPacketListener.java | 2 +- .../packet/SetWorldPropertyListener.java | 6 +- .../WorldPropertyDataType.java | 9 +- .../WorldPropertyWidgetType.java | 5 +- .../server/ServerWorldPropertiesRegistry.java | 97 ++++++++++--------- .../server/ServerWorldProperty.java | 73 ++++++-------- .../server/ServerWorldPropertyHolder.java | 77 +++++++++++++++ 11 files changed, 220 insertions(+), 149 deletions(-) create mode 100644 src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertyHolder.java diff --git a/build.gradle.kts b/build.gradle.kts index ebacafe..eea7a94 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "com.moulberry.axiom" -version = "1.5.2" +version = "1.5.4" description = "Serverside component for Axiom on Paper" java { diff --git a/src/main/java/com/moulberry/axiom/AxiomPaper.java b/src/main/java/com/moulberry/axiom/AxiomPaper.java index ee38eb0..138bb95 100644 --- a/src/main/java/com/moulberry/axiom/AxiomPaper.java +++ b/src/main/java/com/moulberry/axiom/AxiomPaper.java @@ -5,7 +5,6 @@ import com.moulberry.axiom.event.AxiomCreateWorldPropertiesEvent; import com.moulberry.axiom.event.AxiomModifyWorldEvent; import com.moulberry.axiom.packet.*; import com.moulberry.axiom.world_properties.server.ServerWorldPropertiesRegistry; -import com.moulberry.axiom.world_properties.server.ServerWorldProperty; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.papermc.paper.event.player.PlayerFailMoveEvent; @@ -19,11 +18,9 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import org.bukkit.*; import org.bukkit.configuration.Configuration; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -166,7 +163,11 @@ public class AxiomPaper extends JavaPlugin implements Listener { private final WeakHashMap worldProperties = new WeakHashMap<>(); - public @Nullable ServerWorldPropertiesRegistry getWorldProperties(World world) { + public @Nullable ServerWorldPropertiesRegistry getWorldPropertiesIfPresent(World world) { + return worldProperties.get(world); + } + + public @Nullable ServerWorldPropertiesRegistry getOrCreateWorldProperties(World world) { if (worldProperties.containsKey(world)) { return worldProperties.get(world); } else { @@ -207,7 +208,7 @@ public class AxiomPaper extends JavaPlugin implements Listener { public void onChangedWorld(PlayerChangedWorldEvent event) { World world = event.getPlayer().getWorld(); - ServerWorldPropertiesRegistry properties = getWorldProperties(world); + ServerWorldPropertiesRegistry properties = getOrCreateWorldProperties(world); if (properties == null) { event.getPlayer().sendPluginMessage(this, "axiom:register_world_properties", new byte[]{0}); @@ -219,13 +220,7 @@ public class AxiomPaper extends JavaPlugin implements Listener { @EventHandler public void onGameRuleChanged(WorldGameRuleChangeEvent event) { if (event.getGameRule() == GameRule.DO_WEATHER_CYCLE) { - ServerWorldPropertiesRegistry properties = getWorldProperties(event.getWorld()); - if (properties != null) { - ServerWorldProperty property = properties.getById(new ResourceLocation("axiom:pause_weather")); - if (property != null) { - ((ServerWorldProperty)property).setValue(event.getWorld(), !Boolean.parseBoolean(event.getValue())); - } - } + ServerWorldPropertiesRegistry.PAUSE_WEATHER.setValue(event.getWorld(), !Boolean.parseBoolean(event.getValue())); } } diff --git a/src/main/java/com/moulberry/axiom/WorldPropertiesExample.java b/src/main/java/com/moulberry/axiom/WorldPropertiesExample.java index 080fa9e..2decb48 100644 --- a/src/main/java/com/moulberry/axiom/WorldPropertiesExample.java +++ b/src/main/java/com/moulberry/axiom/WorldPropertiesExample.java @@ -5,9 +5,7 @@ import com.moulberry.axiom.world_properties.WorldPropertyCategory; import com.moulberry.axiom.world_properties.WorldPropertyWidgetType; import com.moulberry.axiom.world_properties.server.ServerWorldProperty; import net.kyori.adventure.text.Component; -import net.minecraft.util.Unit; import org.bukkit.NamespacedKey; -import org.bukkit.World; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -15,39 +13,53 @@ import java.util.List; public class WorldPropertiesExample implements Listener { + private static final ServerWorldProperty CHECKBOX = new ServerWorldProperty<>( + new NamespacedKey("axiom", "checkbox"), + "Checkbox", + false, WorldPropertyWidgetType.CHECKBOX, world -> false, + (player, world, bool) -> { + world.sendMessage(Component.text("Checkbox: " + bool)); // Do something with input + return true; // true to sync with client + } + ); + + private static final ServerWorldProperty SLIDER = new ServerWorldProperty<>( + new NamespacedKey("axiom", "slider"), + "Slider", + false, new WorldPropertyWidgetType.Slider(0, 8), + world -> 4, + (player, world, integer) -> { + world.sendMessage(Component.text("Slider: " + integer)); // Do something with input + return true; // true to sync with client + } + ); + + private static final ServerWorldProperty TEXTBOX = new ServerWorldProperty<>( + new NamespacedKey("axiom", "textbox"), + "Textbox", + false, WorldPropertyWidgetType.TEXTBOX, + world -> "Hello", + (player, world, string) -> { + world.sendMessage(Component.text("Textbox: " + string)); // Do something with input + return true; // true to sync with client + } + ); + + private static final ServerWorldProperty BUTTON = new ServerWorldProperty<>( + new NamespacedKey("axiom", "button"), + "Button", + false, WorldPropertyWidgetType.BUTTON, + world -> null, + (player, world, unit) -> { + world.sendMessage(Component.text("Button pressed")); // Do something with input + return true; // true to sync with client + } + ); + @EventHandler public void onCreateWorldProperties(AxiomCreateWorldPropertiesEvent event) { WorldPropertyCategory category = new WorldPropertyCategory("Examples", false); - - ServerWorldProperty checkbox = new ServerWorldProperty<>(new NamespacedKey("axiom", "checkbox"), - "Checkbox", - false, WorldPropertyWidgetType.CHECKBOX, false, (player, world, bool) -> { - world.sendMessage(Component.text("Checkbox: " + bool)); // Do something with input - return true; // true to sync with client - }); - - ServerWorldProperty slider = new ServerWorldProperty<>(new NamespacedKey("axiom", "slider"), - "Slider", - false, new WorldPropertyWidgetType.Slider(0, 8), 4, (player, world, integer) -> { - world.sendMessage(Component.text("Slider: " + integer)); // Do something with input - return true; // true to sync with client - }); - - ServerWorldProperty textbox = new ServerWorldProperty<>(new NamespacedKey("axiom", "textbox"), - "Textbox", - false, WorldPropertyWidgetType.TEXTBOX, "Hello", (player, world, string) -> { - world.sendMessage(Component.text("Textbox: " + string)); // Do something with input - return true; // true to sync with client - }); - - ServerWorldProperty button = new ServerWorldProperty<>(new NamespacedKey("axiom", "button"), - "Button", - false, WorldPropertyWidgetType.BUTTON, Unit.INSTANCE, (player, world, unit) -> { - world.sendMessage(Component.text("Button pressed")); // Do something with input - return true; // true to sync with client - }); - - event.addCategory(category, List.of(checkbox, slider, textbox, button)); + event.addCategory(category, List.of(CHECKBOX, SLIDER, TEXTBOX, BUTTON)); } } diff --git a/src/main/java/com/moulberry/axiom/event/AxiomCreateWorldPropertiesEvent.java b/src/main/java/com/moulberry/axiom/event/AxiomCreateWorldPropertiesEvent.java index 36cf2d9..087355c 100644 --- a/src/main/java/com/moulberry/axiom/event/AxiomCreateWorldPropertiesEvent.java +++ b/src/main/java/com/moulberry/axiom/event/AxiomCreateWorldPropertiesEvent.java @@ -3,13 +3,12 @@ package com.moulberry.axiom.event; import com.moulberry.axiom.world_properties.WorldPropertyCategory; import com.moulberry.axiom.world_properties.server.ServerWorldPropertiesRegistry; import com.moulberry.axiom.world_properties.server.ServerWorldProperty; +import com.moulberry.axiom.world_properties.server.ServerWorldPropertyHolder; import org.bukkit.World; -import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; diff --git a/src/main/java/com/moulberry/axiom/packet/HelloPacketListener.java b/src/main/java/com/moulberry/axiom/packet/HelloPacketListener.java index 9a7a261..62a2322 100644 --- a/src/main/java/com/moulberry/axiom/packet/HelloPacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/HelloPacketListener.java @@ -143,7 +143,7 @@ public class HelloPacketListener implements PluginMessageListener { // Register world properties World world = player.getWorld(); - ServerWorldPropertiesRegistry properties = plugin.getWorldProperties(world); + ServerWorldPropertiesRegistry properties = plugin.getOrCreateWorldProperties(world); if (properties == null) { player.sendPluginMessage(plugin, "axiom:register_world_properties", new byte[]{0}); diff --git a/src/main/java/com/moulberry/axiom/packet/SetWorldPropertyListener.java b/src/main/java/com/moulberry/axiom/packet/SetWorldPropertyListener.java index f1166ec..52d043e 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetWorldPropertyListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetWorldPropertyListener.java @@ -2,7 +2,7 @@ package com.moulberry.axiom.packet; import com.moulberry.axiom.AxiomPaper; import com.moulberry.axiom.world_properties.server.ServerWorldPropertiesRegistry; -import com.moulberry.axiom.world_properties.server.ServerWorldProperty; +import com.moulberry.axiom.world_properties.server.ServerWorldPropertyHolder; import io.netty.buffer.Unpooled; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; @@ -29,10 +29,10 @@ public class SetWorldPropertyListener implements PluginMessageListener { byte[] data = friendlyByteBuf.readByteArray(); int updateId = friendlyByteBuf.readVarInt(); - ServerWorldPropertiesRegistry registry = AxiomPaper.PLUGIN.getWorldProperties(player.getWorld()); + ServerWorldPropertiesRegistry registry = AxiomPaper.PLUGIN.getOrCreateWorldProperties(player.getWorld()); if (registry == null) return; - ServerWorldProperty property = registry.getById(id); + ServerWorldPropertyHolder property = registry.getById(id); if (property != null && property.getType().getTypeId() == type) { property.update(player, player.getWorld(), data); } diff --git a/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyDataType.java b/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyDataType.java index 21f8d85..e3d163d 100644 --- a/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyDataType.java +++ b/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyDataType.java @@ -3,7 +3,6 @@ package com.moulberry.axiom.world_properties; import io.netty.buffer.Unpooled; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.util.Unit; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; @@ -118,20 +117,20 @@ public abstract class WorldPropertyDataType { } }; - public static WorldPropertyDataType EMPTY = new WorldPropertyDataType<>() { + public static WorldPropertyDataType EMPTY = new WorldPropertyDataType<>() { @Override public int getTypeId() { return 5; } @Override - public byte[] serialize(Unit value) { + public byte[] serialize(Void value) { return new byte[0]; } @Override - public Unit deserialize(byte[] bytes) { - return Unit.INSTANCE; + public Void deserialize(byte[] bytes) { + return null; } }; diff --git a/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyWidgetType.java b/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyWidgetType.java index 547aefb..7166324 100644 --- a/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyWidgetType.java +++ b/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyWidgetType.java @@ -1,7 +1,6 @@ package com.moulberry.axiom.world_properties; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Unit; import java.util.List; @@ -62,9 +61,9 @@ public interface WorldPropertyWidgetType { }; - WorldPropertyWidgetType BUTTON = new WorldPropertyWidgetType<>() { + WorldPropertyWidgetType BUTTON = new WorldPropertyWidgetType<>() { @Override - public WorldPropertyDataType dataType() { + public WorldPropertyDataType dataType() { return WorldPropertyDataType.EMPTY; } diff --git a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertiesRegistry.java b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertiesRegistry.java index b19b703..63a8bd9 100644 --- a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertiesRegistry.java +++ b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertiesRegistry.java @@ -6,7 +6,6 @@ import io.netty.buffer.Unpooled; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.GameRules; import org.bukkit.GameRule; import org.bukkit.NamespacedKey; import org.bukkit.World; @@ -14,33 +13,39 @@ import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class ServerWorldPropertiesRegistry { - private final LinkedHashMap>> propertyList = new LinkedHashMap<>(); - private final Map> propertyMap = new HashMap<>(); + private final LinkedHashMap>> propertyList = new LinkedHashMap<>(); + private final Map> propertyMap = new HashMap<>(); + private final World world; public ServerWorldPropertiesRegistry(World world) { - this.registerDefault(world); + this.world = world; + this.registerDefault(); } - public ServerWorldProperty getById(ResourceLocation resourceLocation) { + public ServerWorldPropertyHolder getById(ResourceLocation resourceLocation) { return propertyMap.get(resourceLocation); } + @SuppressWarnings("unchecked") public void addCategory(WorldPropertyCategory category, List> properties) { - this.propertyList.put(category, properties); - + List> holders = new ArrayList<>(); for (ServerWorldProperty property : properties) { - ResourceLocation id = property.getId(); + Object defaultValue = property.defaultValueFunction.apply(this.world); + holders.add(new ServerWorldPropertyHolder<>(defaultValue, (ServerWorldProperty) property)); + } + + this.propertyList.put(category, holders); + + for (ServerWorldPropertyHolder holder : holders) { + ResourceLocation id = holder.getId(); if (this.propertyMap.containsKey(id)) { throw new RuntimeException("Duplicate property: " + id); } - this.propertyMap.put(id, property); + this.propertyMap.put(id, holder); } } @@ -49,7 +54,7 @@ public class ServerWorldPropertiesRegistry { buf.writeVarInt(this.propertyList.size()); - for (Map.Entry>> entry : this.propertyList.entrySet()) { + for (Map.Entry>> entry : this.propertyList.entrySet()) { entry.getKey().write(buf); buf.writeCollection(entry.getValue(), (buffer, p) -> p.write(buffer)); } @@ -59,46 +64,48 @@ public class ServerWorldPropertiesRegistry { bukkitPlayer.sendPluginMessage(plugin, "axiom:register_world_properties", bytes); } - public void registerDefault(World world) { - ServerLevel serverLevel = ((CraftWorld)world).getHandle(); + private static final ServerWorldProperty TIME = new ServerWorldProperty<>( + new NamespacedKey("axiom", "time"), + "axiom.editorui.window.world_properties.time", + true, WorldPropertyWidgetType.TIME, world -> 0, (player, w, integer) -> false + ); + public static final ServerWorldProperty PAUSE_WEATHER = new ServerWorldProperty<>( + new NamespacedKey("axiom", "pause_weather"), + "axiom.editorui.window.world_properties.pause_weather", + true, WorldPropertyWidgetType.CHECKBOX, world -> !world.getGameRuleValue(GameRule.DO_WEATHER_CYCLE), (player, world, bool) -> { + world.setGameRule(GameRule.DO_WEATHER_CYCLE, !bool); + return false; + }); + + private static final ServerWorldProperty WEATHER_TYPE = new ServerWorldProperty<>( + new NamespacedKey("axiom", "weather_type"), + "axiom.editorui.window.world_properties.clear_weather", + true, new WorldPropertyWidgetType.ButtonArray( + List.of("axiom.editorui.window.world_properties.rain_weather", "axiom.editorui.window.world_properties.thunder_weather") + ), world -> 0, (player, world, index) -> { + ServerLevel serverLevel = ((CraftWorld)world).getHandle(); + if (index == 0) { + serverLevel.setWeatherParameters(ServerLevel.RAIN_DELAY.sample(serverLevel.random), 0, false, false); + } else if (index == 1) { + serverLevel.setWeatherParameters(0, ServerLevel.RAIN_DURATION.sample(serverLevel.random), true, false); + } else if (index == 2) { + serverLevel.setWeatherParameters(0, ServerLevel.THUNDER_DURATION.sample(serverLevel.random), true, true); + } + return false; + }); + + public void registerDefault() { // Time WorldPropertyCategory timeCategory = new WorldPropertyCategory("axiom.editorui.window.world_properties.time", true); - ServerWorldProperty time = new ServerWorldProperty<>(new NamespacedKey("axiom", "time"), - "axiom.editorui.window.world_properties.time", - true, WorldPropertyWidgetType.TIME, 0, (player, w, integer) -> false - ); - - this.addCategory(timeCategory, List.of(time)); + this.addCategory(timeCategory, List.of(TIME)); // Weather WorldPropertyCategory weatherCategory = new WorldPropertyCategory("axiom.editorui.window.world_properties.weather", true); - ServerWorldProperty pauseWeather = new ServerWorldProperty<>(new NamespacedKey("axiom", "pause_weather"), - "axiom.editorui.window.world_properties.pause_weather", - true, WorldPropertyWidgetType.CHECKBOX, !world.getGameRuleValue(GameRule.DO_WEATHER_CYCLE), (player, w, bool) -> { - world.setGameRule(GameRule.DO_WEATHER_CYCLE, !bool); - return false; - }); - - ServerWorldProperty weatherType = new ServerWorldProperty<>(new NamespacedKey("axiom", "weather_type"), - "axiom.editorui.window.world_properties.clear_weather", - true, new WorldPropertyWidgetType.ButtonArray( - List.of("axiom.editorui.window.world_properties.rain_weather", "axiom.editorui.window.world_properties.thunder_weather") - ), 0, (player, w, index) -> { - if (index == 0) { - serverLevel.setWeatherParameters(ServerLevel.RAIN_DELAY.sample(serverLevel.random), 0, false, false); - } else if (index == 1) { - serverLevel.setWeatherParameters(0, ServerLevel.RAIN_DURATION.sample(serverLevel.random), true, false); - } else if (index == 2) { - serverLevel.setWeatherParameters(0, ServerLevel.THUNDER_DURATION.sample(serverLevel.random), true, true); - } - return false; - }); - - this.addCategory(weatherCategory, List.of(pauseWeather, weatherType)); + this.addCategory(weatherCategory, List.of(PAUSE_WEATHER, WEATHER_TYPE)); } } diff --git a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldProperty.java b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldProperty.java index 0a2cbda..8749368 100644 --- a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldProperty.java +++ b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldProperty.java @@ -4,32 +4,29 @@ import com.moulberry.axiom.AxiomPaper; import com.moulberry.axiom.world_properties.PropertyUpdateHandler; import com.moulberry.axiom.world_properties.WorldPropertyDataType; import com.moulberry.axiom.world_properties.WorldPropertyWidgetType; -import io.netty.buffer.Unpooled; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import org.bukkit.NamespacedKey; import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey; -import org.bukkit.entity.Player; -import java.util.function.Predicate; +import java.util.function.Function; public class ServerWorldProperty { private final ResourceLocation id; - private final String name; - private final boolean localizeName; - private WorldPropertyWidgetType widget; - private T value; - private PropertyUpdateHandler handler; + /*package-private*/ final String name; + /*package-private*/ final boolean localizeName; + /*package-private*/ WorldPropertyWidgetType widget; + /*package-private*/ Function defaultValueFunction; + /*package-private*/ PropertyUpdateHandler handler; public ServerWorldProperty(NamespacedKey id, String name, boolean localizeName, WorldPropertyWidgetType widget, - T value, PropertyUpdateHandler handler) { + Function defaultValueFunction, PropertyUpdateHandler handler) { this.id = CraftNamespacedKey.toMinecraft(id); this.name = name; this.localizeName = localizeName; this.widget = widget; - this.value = value; + this.defaultValueFunction = defaultValueFunction; this.handler = handler; } @@ -41,44 +38,30 @@ public class ServerWorldProperty { return this.widget.dataType(); } - public void update(Player player, World world, byte[] data) { - this.value = this.widget.dataType().deserialize(data); - if (this.handler.update(player, world, this.value)) { - this.sync(world); - } - } - - public void setValueWithoutSyncing(T value) { - this.value = value; - } - - public void setValue(World world, T value) { - this.value = value; - this.sync(world); - } - - public void sync(World world) { - FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); - - buf.writeResourceLocation(this.id); - buf.writeVarInt(this.widget.dataType().getTypeId()); - buf.writeByteArray(this.widget.dataType().serialize(this.value)); - - byte[] message = new byte[buf.writerIndex()]; - buf.getBytes(0, message); - for (Player player : world.getPlayers()) { - if (AxiomPaper.PLUGIN.activeAxiomPlayers.contains(player.getUniqueId())) { - player.sendPluginMessage(AxiomPaper.PLUGIN, "axiom:set_world_property", message); + @SuppressWarnings("unchecked") + public boolean setValueWithoutSyncing(World world, T value) { + ServerWorldPropertiesRegistry properties = AxiomPaper.PLUGIN.getWorldPropertiesIfPresent(world); + if (properties != null) { + ServerWorldPropertyHolder property = properties.getById(this.id); + if (property != null && property.getProperty() == this) { + ((ServerWorldPropertyHolder)property).setValueWithoutSyncing(value); + return true; } } + return false; } - public void write(FriendlyByteBuf friendlyByteBuf) { - friendlyByteBuf.writeResourceLocation(this.id); - friendlyByteBuf.writeUtf(this.name); - friendlyByteBuf.writeBoolean(this.localizeName); - this.widget.write(friendlyByteBuf); - friendlyByteBuf.writeByteArray(this.widget.dataType().serialize(this.value)); + @SuppressWarnings("unchecked") + public boolean setValue(World world, T value) { + ServerWorldPropertiesRegistry properties = AxiomPaper.PLUGIN.getWorldPropertiesIfPresent(world); + if (properties != null) { + ServerWorldPropertyHolder property = properties.getById(this.id); + if (property != null && property.getProperty() == this) { + ((ServerWorldPropertyHolder)property).setValue(world, value); + return true; + } + } + return false; } } diff --git a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertyHolder.java b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertyHolder.java new file mode 100644 index 0000000..72e1cb9 --- /dev/null +++ b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertyHolder.java @@ -0,0 +1,77 @@ +package com.moulberry.axiom.world_properties.server; + +import com.moulberry.axiom.AxiomPaper; +import com.moulberry.axiom.world_properties.PropertyUpdateHandler; +import com.moulberry.axiom.world_properties.WorldPropertyDataType; +import com.moulberry.axiom.world_properties.WorldPropertyWidgetType; +import io.netty.buffer.Unpooled; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey; +import org.bukkit.entity.Player; + +public class ServerWorldPropertyHolder { + + private T value; + private ServerWorldProperty property; + + public ServerWorldPropertyHolder(T value, ServerWorldProperty property) { + this.value = value; + this.property = property; + } + + public ResourceLocation getId() { + return this.property.getId(); + } + + public WorldPropertyDataType getType() { + return this.property.widget.dataType(); + } + + public ServerWorldProperty getProperty() { + return property; + } + + public void update(Player player, World world, byte[] data) { + this.value = this.property.widget.dataType().deserialize(data); + if (this.property.handler.update(player, world, this.value)) { + this.sync(world); + } + } + + public void setValueWithoutSyncing(T value) { + this.value = value; + } + + public void setValue(World world, T value) { + this.value = value; + this.sync(world); + } + + public void sync(World world) { + FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); + + buf.writeResourceLocation(this.getId()); + buf.writeVarInt(this.property.widget.dataType().getTypeId()); + buf.writeByteArray(this.property.widget.dataType().serialize(this.value)); + + byte[] message = new byte[buf.writerIndex()]; + buf.getBytes(0, message); + for (Player player : world.getPlayers()) { + if (AxiomPaper.PLUGIN.activeAxiomPlayers.contains(player.getUniqueId())) { + player.sendPluginMessage(AxiomPaper.PLUGIN, "axiom:set_world_property", message); + } + } + } + + public void write(FriendlyByteBuf friendlyByteBuf) { + friendlyByteBuf.writeResourceLocation(this.getId()); + friendlyByteBuf.writeUtf(this.property.name); + friendlyByteBuf.writeBoolean(this.property.localizeName); + this.property.widget.write(friendlyByteBuf); + friendlyByteBuf.writeByteArray(this.property.widget.dataType().serialize(this.value)); + } + +}