geforkt von Mirrors/AxiomPaperPlugin
Add basic World Property support + SetTimePacketListener
Dieser Commit ist enthalten in:
Ursprung
95ac82cf73
Commit
1e25490d27
@ -2,6 +2,7 @@ package com.moulberry.axiom;
|
||||
|
||||
import com.moulberry.axiom.buffer.CompressedBlockEntity;
|
||||
import com.moulberry.axiom.packet.*;
|
||||
import com.moulberry.axiom.world_properties.server.ServerWorldPropertiesRegistry;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.papermc.paper.event.player.PlayerFailMoveEvent;
|
||||
@ -18,6 +19,8 @@ import org.bukkit.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.messaging.Messenger;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@ -38,12 +41,14 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:initialize_hotbars");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:set_editor_views");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:block_entities");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:register_world_properties");
|
||||
|
||||
final Set<UUID> activeAxiomPlayers = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
msg.registerIncomingPluginChannel(this, "axiom:hello", new HelloPacketListener(this, activeAxiomPlayers));
|
||||
msg.registerIncomingPluginChannel(this, "axiom:set_gamemode", new SetGamemodePacketListener());
|
||||
msg.registerIncomingPluginChannel(this, "axiom:set_fly_speed", new SetFlySpeedPacketListener());
|
||||
msg.registerIncomingPluginChannel(this, "axiom:set_time", new SetTimePacketListener());
|
||||
msg.registerIncomingPluginChannel(this, "axiom:set_block", new SetBlockPacketListener(this));
|
||||
msg.registerIncomingPluginChannel(this, "axiom:set_hotbar_slot", new SetHotbarSlotPacketListener());
|
||||
msg.registerIncomingPluginChannel(this, "axiom:switch_active_hotbar", new SwitchActiveHotbarPacketListener());
|
||||
@ -97,9 +102,30 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
||||
@EventHandler
|
||||
public void onFailMove(PlayerFailMoveEvent event) {
|
||||
if (event.getPlayer().hasPermission("axiom.*") &&
|
||||
event.getFailReason() == PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY) {
|
||||
event.getFailReason() == PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY) {
|
||||
event.setAllowed(true);
|
||||
}
|
||||
}
|
||||
|
||||
private final WeakHashMap<World, ServerWorldPropertiesRegistry> worldProperties = new WeakHashMap<>();
|
||||
|
||||
@EventHandler
|
||||
public void onChangedWorld(PlayerChangedWorldEvent event) {
|
||||
System.out.println("Changed world!");
|
||||
|
||||
World world = event.getPlayer().getWorld();
|
||||
ServerWorldPropertiesRegistry properties = worldProperties.computeIfAbsent(world, k -> new ServerWorldPropertiesRegistry());
|
||||
properties.registerFor(this, event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> {
|
||||
World world = player.getWorld();
|
||||
ServerWorldPropertiesRegistry properties = worldProperties.computeIfAbsent(world, k -> new ServerWorldPropertiesRegistry());
|
||||
properties.registerFor(this, player);
|
||||
}, 20); // Why does this need to be delayed?
|
||||
}
|
||||
|
||||
}
|
||||
|
56
src/main/java/com/moulberry/axiom/event/AxiomTimeChangeEvent.java
Normale Datei
56
src/main/java/com/moulberry/axiom/event/AxiomTimeChangeEvent.java
Normale Datei
@ -0,0 +1,56 @@
|
||||
package com.moulberry.axiom.event;
|
||||
|
||||
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;
|
||||
|
||||
public class AxiomTimeChangeEvent extends Event implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private final Player player;
|
||||
private final @Nullable Integer time;
|
||||
private final @Nullable Boolean freezeTime;
|
||||
private boolean cancelled = false;
|
||||
|
||||
public AxiomTimeChangeEvent(Player player, @Nullable Integer time, @Nullable Boolean freezeTime) {
|
||||
this.player = player;
|
||||
this.time = time;
|
||||
this.freezeTime = freezeTime;
|
||||
}
|
||||
|
||||
public @Nullable Integer getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public @Nullable Boolean isFreezeTime() {
|
||||
return freezeTime;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
}
|
@ -20,7 +20,6 @@ public class SetFlySpeedPacketListener implements PluginMessageListener {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message));
|
||||
float flySpeed = friendlyByteBuf.readFloat();
|
||||
|
||||
|
47
src/main/java/com/moulberry/axiom/packet/SetTimePacketListener.java
Normale Datei
47
src/main/java/com/moulberry/axiom/packet/SetTimePacketListener.java
Normale Datei
@ -0,0 +1,47 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.event.AxiomFlySpeedChangeEvent;
|
||||
import com.moulberry.axiom.event.AxiomTimeChangeEvent;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SetTimePacketListener implements PluginMessageListener {
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
|
||||
if (!player.hasPermission("axiom.*")) {
|
||||
return;
|
||||
}
|
||||
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message));
|
||||
ResourceKey<Level> key = friendlyByteBuf.readResourceKey(Registries.DIMENSION); // Ignore
|
||||
Integer time = friendlyByteBuf.readNullable(FriendlyByteBuf::readInt);
|
||||
Boolean freezeTime = friendlyByteBuf.readNullable(FriendlyByteBuf::readBoolean);
|
||||
|
||||
if (time == null && freezeTime == null) return;
|
||||
|
||||
ServerLevel level = ((CraftWorld)player.getWorld()).getHandle();
|
||||
if (!level.dimension().equals(key)) return;
|
||||
|
||||
// Call event
|
||||
AxiomTimeChangeEvent timeChangeEvent = new AxiomTimeChangeEvent(player, time, freezeTime);
|
||||
Bukkit.getPluginManager().callEvent(timeChangeEvent);
|
||||
if (timeChangeEvent.isCancelled()) return;
|
||||
|
||||
// Change time
|
||||
if (time != null) level.setDayTime(time);
|
||||
if (freezeTime != null) level.getGameRules().getRule(GameRules.RULE_DAYLIGHT).set(!freezeTime, null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.moulberry.axiom.world_properties;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public record WorldPropertyCategory(String name, boolean localizeName) {
|
||||
|
||||
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||
friendlyByteBuf.writeUtf(this.name);
|
||||
friendlyByteBuf.writeBoolean(this.localizeName);
|
||||
}
|
||||
|
||||
public static WorldPropertyCategory read(FriendlyByteBuf friendlyByteBuf) {
|
||||
return new WorldPropertyCategory(
|
||||
friendlyByteBuf.readUtf(),
|
||||
friendlyByteBuf.readBoolean()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
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.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public abstract class WorldPropertyDataType<T> {
|
||||
|
||||
public abstract int getTypeId();
|
||||
public abstract byte[] serialize(T value);
|
||||
public abstract T deserialize(byte[] bytes);
|
||||
|
||||
public static WorldPropertyDataType<Boolean> BOOLEAN = new WorldPropertyDataType<>() {
|
||||
@Override
|
||||
public int getTypeId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(Boolean value) {
|
||||
return new byte[] { value ? (byte)1 : (byte)0 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deserialize(byte[] bytes) {
|
||||
return bytes[0] != 0;
|
||||
}
|
||||
};
|
||||
|
||||
public static WorldPropertyDataType<Integer> INTEGER = new WorldPropertyDataType<>() {
|
||||
@Override
|
||||
public int getTypeId() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(Integer value) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(8));
|
||||
buf.writeVarInt(value);
|
||||
return buf.accessByteBufWithCorrectSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deserialize(byte[] bytes) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(bytes));
|
||||
return buf.readVarInt();
|
||||
}
|
||||
};
|
||||
|
||||
public static WorldPropertyDataType<String> STRING = new WorldPropertyDataType<>() {
|
||||
@Override
|
||||
public int getTypeId() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(String value) {
|
||||
return value.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deserialize(byte[] bytes) {
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
};
|
||||
|
||||
public static WorldPropertyDataType<Item> ITEM = new WorldPropertyDataType<>() {
|
||||
@Override
|
||||
public int getTypeId() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(Item value) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(8));
|
||||
buf.writeId(BuiltInRegistries.ITEM, value);
|
||||
return buf.accessByteBufWithCorrectSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item deserialize(byte[] bytes) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(bytes));
|
||||
return buf.readById(BuiltInRegistries.ITEM);
|
||||
}
|
||||
};
|
||||
|
||||
public static WorldPropertyDataType<Block> BLOCK = new WorldPropertyDataType<>() {
|
||||
@Override
|
||||
public int getTypeId() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(Block value) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(8));
|
||||
buf.writeId(BuiltInRegistries.BLOCK, value);
|
||||
return buf.accessByteBufWithCorrectSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block deserialize(byte[] bytes) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.wrappedBuffer(bytes));
|
||||
return buf.readById(BuiltInRegistries.BLOCK);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.moulberry.axiom.world_properties;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
public interface WorldPropertyWidgetType<T> {
|
||||
|
||||
WorldPropertyDataType<T> dataType();
|
||||
void write(FriendlyByteBuf friendlyByteBuf);
|
||||
|
||||
static WorldPropertyWidgetType<?> read(FriendlyByteBuf friendlyByteBuf) {
|
||||
int type = friendlyByteBuf.readVarInt();
|
||||
return switch (type) {
|
||||
case 0 -> CHECKBOX;
|
||||
case 1 -> new Slider(friendlyByteBuf.readInt(), friendlyByteBuf.readInt());
|
||||
case 2 -> TEXTBOX;
|
||||
case 3 -> TIME;
|
||||
default -> throw new RuntimeException("Unknown widget type: " + type);
|
||||
};
|
||||
}
|
||||
|
||||
WorldPropertyWidgetType<Boolean> CHECKBOX = new WorldPropertyWidgetType<>() {
|
||||
@Override
|
||||
public WorldPropertyDataType<Boolean> dataType() {
|
||||
return WorldPropertyDataType.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||
friendlyByteBuf.writeVarInt(0);
|
||||
}
|
||||
};
|
||||
|
||||
record Slider(int min, int max) implements WorldPropertyWidgetType<Integer> {
|
||||
@Override
|
||||
public WorldPropertyDataType<Integer> dataType() {
|
||||
return WorldPropertyDataType.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||
friendlyByteBuf.writeVarInt(1);
|
||||
friendlyByteBuf.writeInt(this.min);
|
||||
friendlyByteBuf.writeInt(this.max);
|
||||
}
|
||||
}
|
||||
|
||||
WorldPropertyWidgetType<String> TEXTBOX = new WorldPropertyWidgetType<>() {
|
||||
@Override
|
||||
public WorldPropertyDataType<String> dataType() {
|
||||
return WorldPropertyDataType.STRING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||
friendlyByteBuf.writeVarInt(2);
|
||||
}
|
||||
};
|
||||
|
||||
WorldPropertyWidgetType<Integer> TIME = new WorldPropertyWidgetType<>() {
|
||||
@Override
|
||||
public WorldPropertyDataType<Integer> dataType() {
|
||||
return WorldPropertyDataType.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||
friendlyByteBuf.writeVarInt(3);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.moulberry.axiom.world_properties.server;
|
||||
|
||||
import com.moulberry.axiom.world_properties.WorldPropertyCategory;
|
||||
import com.moulberry.axiom.world_properties.WorldPropertyWidgetType;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
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;
|
||||
|
||||
public class ServerWorldPropertiesRegistry {
|
||||
|
||||
private final LinkedHashMap<WorldPropertyCategory, List<ServerWorldProperty<?>>> propertyList = new LinkedHashMap<>();
|
||||
private final Map<ResourceLocation, ServerWorldProperty<?>> propertyMap = new HashMap<>();
|
||||
|
||||
public ServerWorldPropertiesRegistry() {
|
||||
this.registerDefault();
|
||||
}
|
||||
|
||||
public ServerWorldProperty<?> getById(ResourceLocation resourceLocation) {
|
||||
return propertyMap.get(resourceLocation);
|
||||
}
|
||||
|
||||
public void addCategory(WorldPropertyCategory category, List<ServerWorldProperty<?>> properties) {
|
||||
this.propertyList.put(category, properties);
|
||||
|
||||
for (ServerWorldProperty<?> property : properties) {
|
||||
ResourceLocation id = property.getId();
|
||||
if (this.propertyMap.containsKey(id)) {
|
||||
throw new RuntimeException("Duplicate property: " + id);
|
||||
}
|
||||
this.propertyMap.put(id, property);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerFor(Plugin plugin, Player bukkitPlayer) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
|
||||
buf.writeVarInt(this.propertyList.size());
|
||||
|
||||
for (Map.Entry<WorldPropertyCategory, List<ServerWorldProperty<?>>> entry : this.propertyList.entrySet()) {
|
||||
entry.getKey().write(buf);
|
||||
buf.writeCollection(entry.getValue(), (buffer, p) -> p.write(buffer));
|
||||
}
|
||||
|
||||
bukkitPlayer.sendPluginMessage(plugin, "axiom:register_world_properties",
|
||||
buf.accessByteBufWithCorrectSize());
|
||||
}
|
||||
|
||||
public void registerDefault() {
|
||||
// Time
|
||||
WorldPropertyCategory timeCategory = new WorldPropertyCategory("axiom.editorui.window.world_properties.time", true);
|
||||
|
||||
ServerWorldProperty<Integer> time = new ServerWorldProperty<>(new ResourceLocation("axiom:time"),
|
||||
"axiom.editorui.window.world_properties.time",
|
||||
true, WorldPropertyWidgetType.TIME, 0, integer -> false
|
||||
);
|
||||
|
||||
this.addCategory(timeCategory, List.of(time));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.moulberry.axiom.world_properties.server;
|
||||
|
||||
import com.moulberry.axiom.world_properties.WorldPropertyDataType;
|
||||
import com.moulberry.axiom.world_properties.WorldPropertyWidgetType;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ServerWorldProperty<T> {
|
||||
|
||||
private final ResourceLocation id;
|
||||
private final String name;
|
||||
private final boolean localizeName;
|
||||
private WorldPropertyWidgetType<T> widget;
|
||||
private T value;
|
||||
private Predicate<T> handler;
|
||||
|
||||
public ServerWorldProperty(ResourceLocation id, String name, boolean localizeName, WorldPropertyWidgetType<T> widget,
|
||||
T value, Predicate<T> handler) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.localizeName = localizeName;
|
||||
this.widget = widget;
|
||||
this.value = value;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public ResourceLocation getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public WorldPropertyDataType<T> getType() {
|
||||
return this.widget.dataType();
|
||||
}
|
||||
|
||||
public void update(ServerLevel serverLevel, byte[] data) {
|
||||
this.value = this.widget.dataType().deserialize(data);
|
||||
if (this.handler.test(this.value)) {
|
||||
// AxiomClientboundSetWorldProperty packet = new AxiomClientboundSetWorldProperty(this.id,
|
||||
// this.widget.dataType().getTypeId(), this.widget.dataType().serialize(this.value));
|
||||
|
||||
// for (ServerPlayer player : serverLevel.players()) {
|
||||
// if (player.hasPermissions(2)) packet.send(player);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren