geforkt von Mirrors/AxiomPaperPlugin
Dieser Commit ist enthalten in:
Ursprung
ef7886341e
Commit
b8fa0aa640
@ -22,6 +22,7 @@ repositories {
|
||||
maven("https://jitpack.io")
|
||||
maven("https://maven.enginehub.org/repo/")
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
maven("https://repo.viaversion.com")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -38,6 +39,9 @@ dependencies {
|
||||
implementation(platform("com.intellectualsites.bom:bom-newest:1.37"))
|
||||
compileOnly("com.intellectualsites.plotsquared:plotsquared-core")
|
||||
compileOnly("com.intellectualsites.plotsquared:plotsquared-bukkit") { isTransitive = false }
|
||||
|
||||
// ViaVersion support
|
||||
compileOnly("com.viaversion:viaversion-api:4.7.0")
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
@ -1,16 +1,10 @@
|
||||
package com.moulberry.axiom;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.bukkit.NamespacedKey;
|
||||
|
||||
public class AxiomConstants {
|
||||
|
||||
public static final long MIN_POSITION_LONG = BlockPos.asLong(-33554432, -2048, -33554432);
|
||||
static {
|
||||
if (MIN_POSITION_LONG != 0b1000000000000000000000000010000000000000000000000000100000000000L) {
|
||||
throw new Error("BlockPos representation changed!");
|
||||
}
|
||||
}
|
||||
public static final long MIN_POSITION_LONG = 0b1000000000000000000000000010000000000000000000000000100000000000L;
|
||||
|
||||
public static final int API_VERSION = 5;
|
||||
public static final NamespacedKey ACTIVE_HOTBAR_INDEX = new NamespacedKey("axiom", "active_hotbar_index");
|
||||
|
@ -1,105 +1,67 @@
|
||||
package com.moulberry.axiom;
|
||||
|
||||
import com.moulberry.axiom.buffer.CompressedBlockEntity;
|
||||
import com.moulberry.axiom.integration.PaperFailMoveListener;
|
||||
import com.moulberry.axiom.packet.*;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.papermc.paper.event.player.PlayerFailMoveEvent;
|
||||
import io.papermc.paper.network.ChannelInitializeListener;
|
||||
import io.papermc.paper.network.ChannelInitializeListenerHolder;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.ConnectionProtocol;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.PacketFlow;
|
||||
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.messaging.Messenger;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class AxiomPaper extends JavaPlugin implements Listener {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
CompressedBlockEntity.initialize(this);
|
||||
public static final String PERMISSION = "axiom.*";
|
||||
|
||||
Messenger msg = Bukkit.getMessenger();
|
||||
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:enable");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:initialize_hotbars");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:set_editor_views");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:block_entities");
|
||||
|
||||
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_block", new SetBlockPacketListener(this));
|
||||
msg.registerIncomingPluginChannel(this, "axiom:set_hotbar_slot", new SetHotbarSlotPacketListener());
|
||||
msg.registerIncomingPluginChannel(this, "axiom:switch_active_hotbar", new SwitchActiveHotbarPacketListener());
|
||||
msg.registerIncomingPluginChannel(this, "axiom:teleport", new TeleportPacketListener());
|
||||
msg.registerIncomingPluginChannel(this, "axiom:set_editor_views", new SetEditorViewsPacketListener());
|
||||
msg.registerIncomingPluginChannel(this, "axiom:request_block_entity", new RequestBlockEntityPacketListener(this));
|
||||
|
||||
SetBlockBufferPacketListener setBlockBufferPacketListener = new SetBlockBufferPacketListener(this);
|
||||
|
||||
ChannelInitializeListenerHolder.addListener(Key.key("axiom:handle_big_payload"), new ChannelInitializeListener() {
|
||||
@Override
|
||||
public void afterInitChannel(@NonNull Channel channel) {
|
||||
var packets = ConnectionProtocol.PLAY.getPacketsByIds(PacketFlow.SERVERBOUND);
|
||||
int payloadId = -1;
|
||||
for (Map.Entry<Integer, Class<? extends Packet<?>>> entry : packets.entrySet()) {
|
||||
if (entry.getValue() == ServerboundCustomPayloadPacket.class) {
|
||||
payloadId = entry.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (payloadId < 0) {
|
||||
throw new RuntimeException("Failed to find ServerboundCustomPayloadPacket id");
|
||||
}
|
||||
|
||||
Connection connection = (Connection) channel.pipeline().get("packet_handler");
|
||||
channel.pipeline().addBefore("decoder", "axiom-big-payload-handler",
|
||||
new AxiomBigPayloadHandler(payloadId, connection, setBlockBufferPacketListener));
|
||||
}
|
||||
});
|
||||
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> {
|
||||
HashSet<UUID> newActiveAxiomPlayers = new HashSet<>();
|
||||
|
||||
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
|
||||
if (activeAxiomPlayers.contains(player.getUniqueId())) {
|
||||
if (!player.hasPermission("axiom.*")) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
buf.writeBoolean(false);
|
||||
player.sendPluginMessage(this, "axiom:enable", buf.accessByteBufWithCorrectSize());
|
||||
} else {
|
||||
newActiveAxiomPlayers.add(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activeAxiomPlayers.clear();
|
||||
activeAxiomPlayers.addAll(newActiveAxiomPlayers);
|
||||
}, 20, 20);
|
||||
private static AxiomPaper instance;
|
||||
public static Plugin getPlugin() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onFailMove(PlayerFailMoveEvent event) {
|
||||
if (event.getPlayer().hasPermission("axiom.*") &&
|
||||
event.getFailReason() == PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY) {
|
||||
event.setAllowed(true);
|
||||
private static final Map<String, AxiomPacketListener> listeners = new ConcurrentHashMap<>();
|
||||
|
||||
public static AxiomPacketListener getListener(String channel) {
|
||||
return listeners.get(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
|
||||
try {
|
||||
Bukkit.getPluginManager().registerEvents(new PaperFailMoveListener(), this);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
getLogger().log(Level.WARNING, "Axiom players may move too quickly according to the server. Use a current Paper version or increase the 'moved-too-quickly-multiplier' in spigot.yml.");
|
||||
}
|
||||
|
||||
for(OutChannel channel : OutChannel.values()) {
|
||||
Bukkit.getMessenger().registerOutgoingPluginChannel(this, channel.getChannel());
|
||||
}
|
||||
|
||||
//TODO multiversion (Except setGamemode)
|
||||
registerInChannel("hello", new HelloPacketListener());
|
||||
registerInChannel("set_gamemode", new SetGamemodePacketListener());
|
||||
registerInChannel("set_fly_speed", new SetFlySpeedPacketListener());
|
||||
registerInChannel("set_block", new SetBlockPacketListener());
|
||||
registerInChannel("set_hotbar_slot", new SetHotbarSlotPacketListener());
|
||||
registerInChannel("switch_active_hotbar", new SwitchActiveHotbarPacketListener());
|
||||
registerInChannel("teleport", new TeleportPacketListener());
|
||||
registerInChannel("set_editor_views", new SetEditorViewsPacketListener());
|
||||
registerInChannel("request_block_entity", new RequestBlockEntityPacketListener());
|
||||
registerInChannel("handle_big_payload", new SetBlockBufferPacketListener());
|
||||
}
|
||||
|
||||
private void registerInChannel(String channel, AxiomPacketListener handler) {
|
||||
listeners.put(channel, handler);
|
||||
Bukkit.getMessenger().registerIncomingPluginChannel(this, "axiom:" + channel, (ch, player, message) -> {
|
||||
if (!player.hasPermission(PERMISSION))
|
||||
return;
|
||||
|
||||
handler.onMessage(player, Unpooled.wrappedBuffer(message));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
32
src/main/java/com/moulberry/axiom/OutChannel.java
Normale Datei
32
src/main/java/com/moulberry/axiom/OutChannel.java
Normale Datei
@ -0,0 +1,32 @@
|
||||
package com.moulberry.axiom;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public enum OutChannel {
|
||||
ENABLE,
|
||||
INITIALIZE_HOTBARS,
|
||||
SET_EDITOR_VIEWS,
|
||||
BLOCK_ENTITIES;
|
||||
|
||||
private final String channel;
|
||||
|
||||
OutChannel() {
|
||||
channel = "axiom:" + name();
|
||||
}
|
||||
|
||||
public String getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void send(Player player, ByteBuf buf) {
|
||||
// trustin https://stackoverflow.com/a/19309312 CC BY-SA 3.0
|
||||
byte[] array = new byte[buf.readableBytes()];
|
||||
buf.getBytes(buf.readerIndex(), array);
|
||||
send(player, array);
|
||||
}
|
||||
|
||||
public void send(Player player, byte[] array) {
|
||||
player.sendPluginMessage(AxiomPaper.getPlugin(), channel, array);
|
||||
}
|
||||
}
|
@ -2,8 +2,6 @@ package com.moulberry.axiom;
|
||||
|
||||
import com.moulberry.axiom.persistence.UUIDDataType;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -3,7 +3,6 @@ package com.moulberry.axiom.buffer;
|
||||
import com.github.luben.zstd.Zstd;
|
||||
import com.github.luben.zstd.ZstdDictCompress;
|
||||
import com.github.luben.zstd.ZstdDictDecompress;
|
||||
import com.moulberry.axiom.AxiomPaper;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
@ -13,16 +12,15 @@ import java.util.Objects;
|
||||
|
||||
public record CompressedBlockEntity(int originalSize, byte compressionDict, byte[] compressed) {
|
||||
|
||||
private static ZstdDictCompress zstdDictCompress = null;
|
||||
private static ZstdDictDecompress zstdDictDecompress = null;
|
||||
|
||||
public static void initialize(AxiomPaper plugin) {
|
||||
try (InputStream is = Objects.requireNonNull(plugin.getResource("zstd_dictionaries/block_entities_v1.dict"))) {
|
||||
private static final ZstdDictCompress zstdDictCompress;
|
||||
private static final ZstdDictDecompress zstdDictDecompress;
|
||||
static {
|
||||
try (InputStream is = Objects.requireNonNull(CompressedBlockEntity.class.getClassLoader().getResourceAsStream("zstd_dictionaries/block_entities_v1.dict"))) {
|
||||
byte[] bytes = is.readAllBytes();
|
||||
zstdDictCompress = new ZstdDictCompress(bytes, Zstd.defaultCompressionLevel());
|
||||
zstdDictDecompress = new ZstdDictDecompress(bytes);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.moulberry.axiom.buffer;
|
||||
|
||||
import com.moulberry.axiom.AxiomConstants;
|
||||
import com.moulberry.axiom.AxiomPaper;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.moulberry.axiom.event;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.moulberry.axiom.event;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.moulberry.axiom.event;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
|
@ -0,0 +1,18 @@
|
||||
package com.moulberry.axiom.integration;
|
||||
|
||||
import com.moulberry.axiom.AxiomPaper;
|
||||
import io.papermc.paper.event.player.PlayerFailMoveEvent;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class PaperFailMoveListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onFailMove(PlayerFailMoveEvent event) {
|
||||
if (event.getPlayer().hasPermission(AxiomPaper.PERMISSION) &&
|
||||
event.getFailReason() == PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY) {
|
||||
event.setAllowed(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
22
src/main/java/com/moulberry/axiom/integration/VersionTranslator.java
Normale Datei
22
src/main/java/com/moulberry/axiom/integration/VersionTranslator.java
Normale Datei
@ -0,0 +1,22 @@
|
||||
package com.moulberry.axiom.integration;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
public interface VersionTranslator {
|
||||
|
||||
VersionTranslator impl = Bukkit.getPluginManager().getPlugin("ViaVersion") != null ? new ViaVersionTranslator() : new Dummy();
|
||||
|
||||
IntFunction<Integer> blockStateMapper(Player player);
|
||||
|
||||
class Dummy implements VersionTranslator {
|
||||
|
||||
@Override
|
||||
public IntFunction<Integer> blockStateMapper(Player player) {
|
||||
return id -> id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
14
src/main/java/com/moulberry/axiom/integration/ViaVersionDummy.java
Normale Datei
14
src/main/java/com/moulberry/axiom/integration/ViaVersionDummy.java
Normale Datei
@ -0,0 +1,14 @@
|
||||
package com.moulberry.axiom.integration;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
public class ViaVersionDummy implements VersionTranslator {
|
||||
|
||||
@Override
|
||||
public IntFunction<Integer> blockStateMapper(Player player) {
|
||||
return id -> id;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package com.moulberry.axiom.integration;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolManager;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
public class ViaVersionTranslator implements VersionTranslator {
|
||||
|
||||
private final ProtocolManager protocolManager;
|
||||
private final ServerProtocolVersion serverVersion;
|
||||
|
||||
public ViaVersionTranslator() {
|
||||
protocolManager = Via.getManager().getProtocolManager();
|
||||
serverVersion = Via.getAPI().getServerVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntFunction<Integer> blockStateMapper(Player player) {
|
||||
List<ProtocolPathEntry> path = protocolManager.getProtocolPath(Via.getAPI().getPlayerVersion(player.getUniqueId()), serverVersion.highestSupportedVersion());
|
||||
if(path == null)
|
||||
return id -> id;
|
||||
|
||||
List<IntFunction<Integer>> mappers = new ArrayList<>(path.size());
|
||||
for(ProtocolPathEntry entry : path) {
|
||||
MappingData mappings = entry.protocol().getMappingData();
|
||||
if(mappings != null)
|
||||
mappers.add(mappings::getNewBlockStateId);
|
||||
}
|
||||
|
||||
return id -> {
|
||||
for(IntFunction<Integer> transformer : mappers)
|
||||
id = transformer.apply(id);
|
||||
return id;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -1,64 +1,63 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.AxiomPaper;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.papermc.paper.network.ConnectionEvent;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.ConnectionProtocol;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.protocol.PacketFlow;
|
||||
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@ChannelHandler.Sharable
|
||||
public class AxiomBigPayloadHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
public class AxiomBigPayloadHandler extends ByteToMessageDecoder {
|
||||
private static final int PLUGINMESSAGE_PACKETID = ConnectionProtocol.PLAY.getPacketId(PacketFlow.SERVERBOUND, new ServerboundCustomPayloadPacket(null, null));
|
||||
|
||||
private static final ResourceLocation SET_BUFFER = new ResourceLocation("axiom", "set_buffer");
|
||||
private final int payloadId;
|
||||
private final Connection connection;
|
||||
private final SetBlockBufferPacketListener listener;
|
||||
private final Player player;
|
||||
|
||||
public AxiomBigPayloadHandler(int payloadId, Connection connection, SetBlockBufferPacketListener listener) {
|
||||
this.payloadId = payloadId;
|
||||
this.connection = connection;
|
||||
this.listener = listener;
|
||||
public AxiomBigPayloadHandler(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
try {
|
||||
int readerIndex = in.readerIndex();
|
||||
int i = in.readableBytes();
|
||||
if (i != 0) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(in);
|
||||
int packetId = buf.readVarInt();
|
||||
|
||||
if (packetId == payloadId) {
|
||||
ResourceLocation identifier = buf.readResourceLocation();
|
||||
if (identifier.equals(SET_BUFFER)) {
|
||||
ServerPlayer player = connection.getPlayer();
|
||||
if (player != null && player.getBukkitEntity().hasPermission("axiom.*")) {
|
||||
if (listener.onReceive(player, buf)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
in.readerIndex(readerIndex);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) throws Exception {
|
||||
if(!(msg instanceof ByteBuf in)) {
|
||||
ctx.fireChannelRead(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.fireChannelRead(in.retain());
|
||||
int readerIndexBackup = in.readerIndex();
|
||||
|
||||
if(in.readableBytes() != 0) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf((ByteBuf) msg);
|
||||
|
||||
if (buf.readVarInt() == PLUGINMESSAGE_PACKETID) {
|
||||
ResourceLocation identifier = buf.readResourceLocation();
|
||||
if (identifier.getNamespace().equals("axiom") && player.hasPermission(AxiomPaper.PERMISSION)) {
|
||||
AxiomPacketListener listener = AxiomPaper.getListener(identifier.getPath());
|
||||
//TODO sync!
|
||||
listener.onMessage(player, in);
|
||||
in.release();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in.readerIndex(readerIndexBackup);
|
||||
ctx.fireChannelRead(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||
if (evt == ConnectionEvent.COMPRESSION_THRESHOLD_SET || evt == ConnectionEvent.COMPRESSION_DISABLED) {
|
||||
ctx.channel().pipeline().remove("axiom-big-payload-handler");
|
||||
ctx.channel().pipeline().addBefore("decoder", "axiom-big-payload-handler",
|
||||
new AxiomBigPayloadHandler(payloadId, connection, listener));
|
||||
ctx.channel().pipeline().addBefore("decoder", "axiom-big-payload-handler", this);
|
||||
}
|
||||
super.userEventTriggered(ctx, evt);
|
||||
}
|
||||
|
10
src/main/java/com/moulberry/axiom/packet/AxiomPacketListener.java
Normale Datei
10
src/main/java/com/moulberry/axiom/packet/AxiomPacketListener.java
Normale Datei
@ -0,0 +1,10 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface AxiomPacketListener {
|
||||
|
||||
void onMessage(Player player, ByteBuf buf);
|
||||
|
||||
}
|
@ -2,49 +2,62 @@ package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.AxiomConstants;
|
||||
import com.moulberry.axiom.AxiomPaper;
|
||||
import com.moulberry.axiom.OutChannel;
|
||||
import com.moulberry.axiom.View;
|
||||
import com.moulberry.axiom.event.AxiomHandshakeEvent;
|
||||
import com.moulberry.axiom.persistence.ItemStackDataType;
|
||||
import com.moulberry.axiom.persistence.UUIDDataType;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class HelloPacketListener implements PluginMessageListener {
|
||||
public class HelloPacketListener implements AxiomPacketListener, Listener {
|
||||
|
||||
private final AxiomPaper plugin;
|
||||
private final Set<UUID> activeAxiomPlayers;
|
||||
private final Set<Player> axiomPlayers = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
public HelloPacketListener(AxiomPaper plugin, Set<UUID> activeAxiomPlayers) {
|
||||
this.plugin = plugin;
|
||||
this.activeAxiomPlayers = activeAxiomPlayers;
|
||||
public HelloPacketListener() {
|
||||
//TODO cleanup (side effects of class)
|
||||
Bukkit.getPluginManager().registerEvents(this, AxiomPaper.getPlugin());
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(AxiomPaper.getPlugin(), () -> axiomPlayers.removeIf(player -> {
|
||||
if (!player.hasPermission(AxiomPaper.PERMISSION)) {
|
||||
OutChannel.ENABLE.send(player, new byte[] { 0 });
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}), 20, 20);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
axiomPlayers.remove(event.getPlayer());
|
||||
}
|
||||
|
||||
@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));
|
||||
public void onMessage(Player player, ByteBuf buf) {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
int apiVersion = friendlyByteBuf.readVarInt();
|
||||
friendlyByteBuf.readNbt(); // Discard
|
||||
|
||||
if (apiVersion != AxiomConstants.API_VERSION) {
|
||||
player.kick(Component.text("Unsupported Axiom API Version. Server supports " + AxiomConstants.API_VERSION +
|
||||
", while client is " + apiVersion));
|
||||
player.sendMessage(Component.text("Unsupported Axiom API Version. Server supports " + AxiomConstants.API_VERSION + ", while client is " + apiVersion));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -55,52 +68,54 @@ public class HelloPacketListener implements PluginMessageListener {
|
||||
return;
|
||||
}
|
||||
|
||||
activeAxiomPlayers.add(player.getUniqueId());
|
||||
axiomPlayers.add(player);
|
||||
//TODO thread safety
|
||||
((CraftPlayer)player).getHandle().connection.connection.channel.pipeline().addBefore("decoder", "axiom-big-payload-handler", new AxiomBigPayloadHandler(player));
|
||||
|
||||
// Enable
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
buf.writeBoolean(true);
|
||||
buf.writeByte(0); // todo: world properties
|
||||
buf.writeInt(handshakeEvent.getMaxBufferSize()); // Max Buffer Size
|
||||
buf.writeBoolean(false); // No source info
|
||||
buf.writeBoolean(false); // No source settings
|
||||
buf.writeVarInt(5); // Maximum Reach
|
||||
buf.writeVarInt(16); // Max editor views
|
||||
buf.writeBoolean(true); // Editable Views
|
||||
player.sendPluginMessage(this.plugin, "axiom:enable", buf.accessByteBufWithCorrectSize());
|
||||
FriendlyByteBuf out = new FriendlyByteBuf(Unpooled.buffer());
|
||||
out.writeBoolean(true);
|
||||
out.writeByte(0); // todo: world properties
|
||||
out.writeInt(handshakeEvent.getMaxBufferSize()); // Max Buffer Size
|
||||
out.writeBoolean(false); // No source info
|
||||
out.writeBoolean(false); // No source settings
|
||||
out.writeVarInt(5); // Maximum Reach
|
||||
out.writeVarInt(16); // Max editor views
|
||||
out.writeBoolean(true); // Editable Views
|
||||
OutChannel.ENABLE.send(player, out);
|
||||
|
||||
// Initialize Hotbars
|
||||
PersistentDataContainer container = player.getPersistentDataContainer();
|
||||
int activeHotbarIndex = container.getOrDefault(AxiomConstants.ACTIVE_HOTBAR_INDEX, PersistentDataType.BYTE, (byte) 0);
|
||||
PersistentDataContainer hotbarItems = container.get(AxiomConstants.HOTBAR_DATA, PersistentDataType.TAG_CONTAINER);
|
||||
if (hotbarItems != null) {
|
||||
buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
buf.writeByte((byte) activeHotbarIndex);
|
||||
out = new FriendlyByteBuf(Unpooled.buffer());
|
||||
out.writeByte((byte) activeHotbarIndex);
|
||||
for (int i=0; i<9*9; i++) {
|
||||
// Ignore selected hotbar
|
||||
if (i / 9 == activeHotbarIndex) {
|
||||
buf.writeItem(net.minecraft.world.item.ItemStack.EMPTY);
|
||||
out.writeItem(net.minecraft.world.item.ItemStack.EMPTY);
|
||||
} else {
|
||||
ItemStack stack = hotbarItems.get(new NamespacedKey("axiom", "slot_"+i), ItemStackDataType.INSTANCE);
|
||||
buf.writeItem(CraftItemStack.asNMSCopy(stack));
|
||||
out.writeItem(CraftItemStack.asNMSCopy(stack));
|
||||
}
|
||||
}
|
||||
player.sendPluginMessage(this.plugin, "axiom:initialize_hotbars", buf.accessByteBufWithCorrectSize());
|
||||
OutChannel.INITIALIZE_HOTBARS.send(player, out);
|
||||
}
|
||||
|
||||
// Initialize Views
|
||||
UUID activeView = container.get(AxiomConstants.ACTIVE_VIEW, UUIDDataType.INSTANCE);
|
||||
if (activeView != null) {
|
||||
buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
buf.writeUUID(activeView);
|
||||
out = new FriendlyByteBuf(Unpooled.buffer());
|
||||
out.writeUUID(activeView);
|
||||
|
||||
PersistentDataContainer[] views = container.get(AxiomConstants.VIEWS, PersistentDataType.TAG_CONTAINER_ARRAY);
|
||||
buf.writeVarInt(views.length);
|
||||
out.writeVarInt(views.length);
|
||||
for (PersistentDataContainer view : views) {
|
||||
View.load(view).write(buf);
|
||||
View.load(view).write(out);
|
||||
}
|
||||
|
||||
player.sendPluginMessage(this.plugin, "axiom:set_editor_views", buf.accessByteBufWithCorrectSize());
|
||||
OutChannel.SET_EDITOR_VIEWS.send(player, out);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.AxiomPaper;
|
||||
import com.moulberry.axiom.OutChannel;
|
||||
import com.moulberry.axiom.buffer.CompressedBlockEntity;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.longs.*;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
@ -16,27 +18,20 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
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;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class RequestBlockEntityPacketListener implements PluginMessageListener {
|
||||
|
||||
private final AxiomPaper plugin;
|
||||
|
||||
public RequestBlockEntityPacketListener(AxiomPaper plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
public class RequestBlockEntityPacketListener implements AxiomPacketListener {
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player bukkitPlayer, @NotNull byte[] message) {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message));
|
||||
public void onMessage(@NotNull Player bukkitPlayer, @NotNull ByteBuf buf) {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
long id = friendlyByteBuf.readLong();
|
||||
|
||||
if (!bukkitPlayer.hasPermission("axiom.*")) {
|
||||
// We always send an 'empty' response in order to make the client happy
|
||||
sendEmptyResponse(bukkitPlayer, id);
|
||||
sendEmptyResponse(bukkitPlayer, id); //TODO
|
||||
return;
|
||||
}
|
||||
|
||||
@ -70,21 +65,21 @@ public class RequestBlockEntityPacketListener implements PluginMessageListener {
|
||||
}
|
||||
|
||||
// Send response packet
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(16));
|
||||
buf.writeLong(id);
|
||||
buf.writeVarInt(map.size());
|
||||
FriendlyByteBuf out = new FriendlyByteBuf(Unpooled.buffer(16));
|
||||
out.writeLong(id);
|
||||
out.writeVarInt(map.size());
|
||||
for (Long2ObjectMap.Entry<CompressedBlockEntity> entry : map.long2ObjectEntrySet()) {
|
||||
buf.writeLong(entry.getLongKey());
|
||||
entry.getValue().write(buf);
|
||||
out.writeLong(entry.getLongKey());
|
||||
entry.getValue().write(out);
|
||||
}
|
||||
bukkitPlayer.sendPluginMessage(this.plugin, "axiom:block_entities", buf.accessByteBufWithCorrectSize());
|
||||
OutChannel.BLOCK_ENTITIES.send(bukkitPlayer, out);
|
||||
}
|
||||
|
||||
private void sendEmptyResponse(Player player, long id) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(16));
|
||||
ByteBuf buf = Unpooled.buffer(16);
|
||||
buf.writeLong(id);
|
||||
buf.writeByte(0); // no block entities
|
||||
player.sendPluginMessage(this.plugin, "axiom:block_entities", buf.accessByteBufWithCorrectSize());
|
||||
OutChannel.BLOCK_ENTITIES.send(player, buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,26 +1,11 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.AxiomPaper;
|
||||
import com.moulberry.axiom.buffer.BiomeBuffer;
|
||||
import com.moulberry.axiom.buffer.BlockBuffer;
|
||||
import com.moulberry.axiom.buffer.CompressedBlockEntity;
|
||||
import com.moulberry.axiom.event.AxiomModifyWorldEvent;
|
||||
import com.moulberry.axiom.integration.RegionProtection;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.WorldGuard;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.regions.RegionContainer;
|
||||
import com.sk89q.worldguard.protection.regions.RegionQuery;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@ -48,26 +33,19 @@ import net.minecraft.world.level.chunk.PalettedContainer;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.level.lighting.LightEngine;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.CraftServer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
public class SetBlockBufferPacketListener {
|
||||
public class SetBlockBufferPacketListener implements AxiomPacketListener {
|
||||
|
||||
private final AxiomPaper plugin;
|
||||
private final Method updateBlockEntityTicker;
|
||||
|
||||
public SetBlockBufferPacketListener(AxiomPaper plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
public SetBlockBufferPacketListener() {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
String methodName = reflectionRemapper.remapMethodName(LevelChunk.class, "updateBlockEntityTicker", BlockEntity.class);
|
||||
|
||||
@ -80,9 +58,11 @@ public class SetBlockBufferPacketListener {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onReceive(ServerPlayer player, FriendlyByteBuf friendlyByteBuf) {
|
||||
MinecraftServer server = player.getServer();
|
||||
if (server == null) return false;
|
||||
@Override
|
||||
public void onMessage(Player player, ByteBuf buf) {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
MinecraftServer server = ((CraftServer)player.getServer()).getServer();
|
||||
if (server == null) return;
|
||||
|
||||
ResourceKey<Level> worldKey = friendlyByteBuf.readResourceKey(Registries.DIMENSION);
|
||||
friendlyByteBuf.readUUID(); // Discard, we don't need to associate buffers
|
||||
@ -102,205 +82,199 @@ public class SetBlockBufferPacketListener {
|
||||
} else {
|
||||
throw new RuntimeException("Unknown buffer type: " + type);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void applyBlockBuffer(ServerPlayer player, MinecraftServer server, BlockBuffer buffer, ResourceKey<Level> worldKey) {
|
||||
server.execute(() -> {
|
||||
ServerLevel world = server.getLevel(worldKey);
|
||||
if (world == null) return;
|
||||
private void applyBlockBuffer(Player player, MinecraftServer server, BlockBuffer buffer, ResourceKey<Level> worldKey) {
|
||||
ServerLevel world = server.getLevel(worldKey);
|
||||
if (world == null) return;
|
||||
|
||||
// Call AxiomModifyWorldEvent event
|
||||
AxiomModifyWorldEvent modifyWorldEvent = new AxiomModifyWorldEvent(player.getBukkitEntity(), world.getWorld());
|
||||
Bukkit.getPluginManager().callEvent(modifyWorldEvent);
|
||||
if (modifyWorldEvent.isCancelled()) return;
|
||||
// Call AxiomModifyWorldEvent event
|
||||
AxiomModifyWorldEvent modifyWorldEvent = new AxiomModifyWorldEvent(player, world.getWorld());
|
||||
Bukkit.getPluginManager().callEvent(modifyWorldEvent);
|
||||
if (modifyWorldEvent.isCancelled()) return;
|
||||
|
||||
RegionProtection regionProtection = new RegionProtection(player.getBukkitEntity(), world.getWorld());
|
||||
RegionProtection regionProtection = new RegionProtection(player, world.getWorld());
|
||||
|
||||
// Allowed, apply buffer
|
||||
BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos();
|
||||
// Allowed, apply buffer
|
||||
BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos();
|
||||
|
||||
var lightEngine = world.getChunkSource().getLightEngine();
|
||||
var lightEngine = world.getChunkSource().getLightEngine();
|
||||
|
||||
BlockState emptyState = BlockBuffer.EMPTY_STATE;
|
||||
BlockState emptyState = BlockBuffer.EMPTY_STATE;
|
||||
|
||||
for (Long2ObjectMap.Entry<PalettedContainer<BlockState>> entry : buffer.entrySet()) {
|
||||
int cx = BlockPos.getX(entry.getLongKey());
|
||||
int cy = BlockPos.getY(entry.getLongKey());
|
||||
int cz = BlockPos.getZ(entry.getLongKey());
|
||||
PalettedContainer<BlockState> container = entry.getValue();
|
||||
for (Long2ObjectMap.Entry<PalettedContainer<BlockState>> entry : buffer.entrySet()) {
|
||||
int cx = BlockPos.getX(entry.getLongKey());
|
||||
int cy = BlockPos.getY(entry.getLongKey());
|
||||
int cz = BlockPos.getZ(entry.getLongKey());
|
||||
PalettedContainer<BlockState> container = entry.getValue();
|
||||
|
||||
if (cy < world.getMinSection() || cy >= world.getMaxSection()) {
|
||||
continue;
|
||||
if (cy < world.getMinSection() || cy >= world.getMaxSection()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!regionProtection.canBuildInSection(cx, cy, cz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LevelChunk chunk = world.getChunk(cx, cz);
|
||||
chunk.setUnsaved(true);
|
||||
|
||||
LevelChunkSection section = chunk.getSection(world.getSectionIndexFromSectionY(cy));
|
||||
PalettedContainer<BlockState> sectionStates = section.getStates();
|
||||
boolean hasOnlyAir = section.hasOnlyAir();
|
||||
|
||||
Heightmap worldSurface = null;
|
||||
Heightmap oceanFloor = null;
|
||||
Heightmap motionBlocking = null;
|
||||
Heightmap motionBlockingNoLeaves = null;
|
||||
for (Map.Entry<Heightmap.Types, Heightmap> heightmap : chunk.getHeightmaps()) {
|
||||
switch (heightmap.getKey()) {
|
||||
case WORLD_SURFACE -> worldSurface = heightmap.getValue();
|
||||
case OCEAN_FLOOR -> oceanFloor = heightmap.getValue();
|
||||
case MOTION_BLOCKING -> motionBlocking = heightmap.getValue();
|
||||
case MOTION_BLOCKING_NO_LEAVES -> motionBlockingNoLeaves = heightmap.getValue();
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
if (!regionProtection.canBuildInSection(cx, cy, cz)) {
|
||||
continue;
|
||||
}
|
||||
Short2ObjectMap<CompressedBlockEntity> blockEntityChunkMap = buffer.getBlockEntityChunkMap(entry.getLongKey());
|
||||
|
||||
LevelChunk chunk = world.getChunk(cx, cz);
|
||||
chunk.setUnsaved(true);
|
||||
sectionStates.acquire();
|
||||
try {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
BlockState blockState = container.get(x, y, z);
|
||||
if (blockState == emptyState) continue;
|
||||
|
||||
LevelChunkSection section = chunk.getSection(world.getSectionIndexFromSectionY(cy));
|
||||
PalettedContainer<BlockState> sectionStates = section.getStates();
|
||||
boolean hasOnlyAir = section.hasOnlyAir();
|
||||
int bx = cx*16 + x;
|
||||
int by = cy*16 + y;
|
||||
int bz = cz*16 + z;
|
||||
|
||||
Heightmap worldSurface = null;
|
||||
Heightmap oceanFloor = null;
|
||||
Heightmap motionBlocking = null;
|
||||
Heightmap motionBlockingNoLeaves = null;
|
||||
for (Map.Entry<Heightmap.Types, Heightmap> heightmap : chunk.getHeightmaps()) {
|
||||
switch (heightmap.getKey()) {
|
||||
case WORLD_SURFACE -> worldSurface = heightmap.getValue();
|
||||
case OCEAN_FLOOR -> oceanFloor = heightmap.getValue();
|
||||
case MOTION_BLOCKING -> motionBlocking = heightmap.getValue();
|
||||
case MOTION_BLOCKING_NO_LEAVES -> motionBlockingNoLeaves = heightmap.getValue();
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
blockPos.set(bx, by, bz);
|
||||
|
||||
Short2ObjectMap<CompressedBlockEntity> blockEntityChunkMap = buffer.getBlockEntityChunkMap(entry.getLongKey());
|
||||
if (hasOnlyAir && blockState.isAir()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sectionStates.acquire();
|
||||
try {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
BlockState blockState = container.get(x, y, z);
|
||||
if (blockState == emptyState) continue;
|
||||
BlockState old = section.setBlockState(x, y, z, blockState, false);
|
||||
if (blockState != old) {
|
||||
Block block = blockState.getBlock();
|
||||
motionBlocking.update(x, by, z, blockState);
|
||||
motionBlockingNoLeaves.update(x, by, z, blockState);
|
||||
oceanFloor.update(x, by, z, blockState);
|
||||
worldSurface.update(x, by, z, blockState);
|
||||
|
||||
int bx = cx*16 + x;
|
||||
int by = cy*16 + y;
|
||||
int bz = cz*16 + z;
|
||||
if (false) { // Full update
|
||||
old.onRemove(world, blockPos, blockState, false);
|
||||
|
||||
blockPos.set(bx, by, bz);
|
||||
|
||||
if (hasOnlyAir && blockState.isAir()) {
|
||||
continue;
|
||||
if (sectionStates.get(x, y, z).is(block)) {
|
||||
blockState.onPlace(world, blockPos, old, false);
|
||||
}
|
||||
}
|
||||
|
||||
BlockState old = section.setBlockState(x, y, z, blockState, false);
|
||||
if (blockState != old) {
|
||||
Block block = blockState.getBlock();
|
||||
motionBlocking.update(x, by, z, blockState);
|
||||
motionBlockingNoLeaves.update(x, by, z, blockState);
|
||||
oceanFloor.update(x, by, z, blockState);
|
||||
worldSurface.update(x, by, z, blockState);
|
||||
if (blockState.hasBlockEntity()) {
|
||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||
|
||||
if (false) { // Full update
|
||||
old.onRemove(world, blockPos, blockState, false);
|
||||
|
||||
if (sectionStates.get(x, y, z).is(block)) {
|
||||
blockState.onPlace(world, blockPos, old, false);
|
||||
if (blockEntity == null) {
|
||||
// There isn't a block entity here, create it!
|
||||
blockEntity = ((EntityBlock)block).newBlockEntity(blockPos, blockState);
|
||||
if (blockEntity != null) {
|
||||
chunk.addAndRegisterBlockEntity(blockEntity);
|
||||
}
|
||||
}
|
||||
} else if (blockEntity.getType().isValid(blockState)) {
|
||||
// Block entity is here and the type is correct
|
||||
blockEntity.setBlockState(blockState);
|
||||
|
||||
if (blockState.hasBlockEntity()) {
|
||||
BlockEntity blockEntity = chunk.getBlockEntity(blockPos, LevelChunk.EntityCreationType.CHECK);
|
||||
|
||||
if (blockEntity == null) {
|
||||
// There isn't a block entity here, create it!
|
||||
blockEntity = ((EntityBlock)block).newBlockEntity(blockPos, blockState);
|
||||
if (blockEntity != null) {
|
||||
chunk.addAndRegisterBlockEntity(blockEntity);
|
||||
}
|
||||
} else if (blockEntity.getType().isValid(blockState)) {
|
||||
// Block entity is here and the type is correct
|
||||
blockEntity.setBlockState(blockState);
|
||||
|
||||
try {
|
||||
this.updateBlockEntityTicker.invoke(chunk, blockEntity);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
// Block entity type isn't correct, we need to recreate it
|
||||
chunk.removeBlockEntity(blockPos);
|
||||
|
||||
blockEntity = ((EntityBlock)block).newBlockEntity(blockPos, blockState);
|
||||
if (blockEntity != null) {
|
||||
chunk.addAndRegisterBlockEntity(blockEntity);
|
||||
}
|
||||
try {
|
||||
this.updateBlockEntityTicker.invoke(chunk, blockEntity);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (blockEntity != null && blockEntityChunkMap != null) {
|
||||
int key = x | (y << 4) | (z << 8);
|
||||
CompressedBlockEntity savedBlockEntity = blockEntityChunkMap.get((short) key);
|
||||
if (savedBlockEntity != null) {
|
||||
blockEntity.load(savedBlockEntity.decompress());
|
||||
}
|
||||
}
|
||||
} else if (old.hasBlockEntity()) {
|
||||
} else {
|
||||
// Block entity type isn't correct, we need to recreate it
|
||||
chunk.removeBlockEntity(blockPos);
|
||||
}
|
||||
|
||||
world.getChunkSource().blockChanged(blockPos); // todo: maybe simply resend chunk instead of this?
|
||||
|
||||
if (LightEngine.hasDifferentLightProperties(chunk, blockPos, old, blockState)) {
|
||||
lightEngine.checkBlock(blockPos);
|
||||
blockEntity = ((EntityBlock)block).newBlockEntity(blockPos, blockState);
|
||||
if (blockEntity != null) {
|
||||
chunk.addAndRegisterBlockEntity(blockEntity);
|
||||
}
|
||||
}
|
||||
if (blockEntity != null && blockEntityChunkMap != null) {
|
||||
int key = x | (y << 4) | (z << 8);
|
||||
CompressedBlockEntity savedBlockEntity = blockEntityChunkMap.get((short) key);
|
||||
if (savedBlockEntity != null) {
|
||||
blockEntity.load(savedBlockEntity.decompress());
|
||||
}
|
||||
}
|
||||
} else if (old.hasBlockEntity()) {
|
||||
chunk.removeBlockEntity(blockPos);
|
||||
}
|
||||
|
||||
world.getChunkSource().blockChanged(blockPos); // todo: maybe simply resend chunk instead of this?
|
||||
|
||||
if (LightEngine.hasDifferentLightProperties(chunk, blockPos, old, blockState)) {
|
||||
lightEngine.checkBlock(blockPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
sectionStates.release();
|
||||
}
|
||||
|
||||
boolean nowHasOnlyAir = section.hasOnlyAir();
|
||||
if (hasOnlyAir != nowHasOnlyAir) {
|
||||
world.getChunkSource().getLightEngine().updateSectionStatus(SectionPos.of(cx, cy, cz), nowHasOnlyAir);
|
||||
}
|
||||
} finally {
|
||||
sectionStates.release();
|
||||
}
|
||||
});
|
||||
|
||||
boolean nowHasOnlyAir = section.hasOnlyAir();
|
||||
if (hasOnlyAir != nowHasOnlyAir) {
|
||||
world.getChunkSource().getLightEngine().updateSectionStatus(SectionPos.of(cx, cy, cz), nowHasOnlyAir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void applyBiomeBuffer(MinecraftServer server, BiomeBuffer biomeBuffer, ResourceKey<Level> worldKey) {
|
||||
server.execute(() -> {
|
||||
ServerLevel world = server.getLevel(worldKey);
|
||||
if (world == null) return;
|
||||
ServerLevel world = server.getLevel(worldKey);
|
||||
if (world == null) return;
|
||||
|
||||
Set<LevelChunk> changedChunks = new HashSet<>();
|
||||
Set<LevelChunk> changedChunks = new HashSet<>();
|
||||
|
||||
int minSection = world.getMinSection();
|
||||
int maxSection = world.getMaxSection();
|
||||
int minSection = world.getMinSection();
|
||||
int maxSection = world.getMaxSection();
|
||||
|
||||
Optional<Registry<Biome>> registryOptional = world.registryAccess().registry(Registries.BIOME);
|
||||
if (registryOptional.isEmpty()) return;
|
||||
Optional<Registry<Biome>> registryOptional = world.registryAccess().registry(Registries.BIOME);
|
||||
if (registryOptional.isEmpty()) return;
|
||||
|
||||
Registry<Biome> registry = registryOptional.get();
|
||||
Registry<Biome> registry = registryOptional.get();
|
||||
|
||||
biomeBuffer.forEachEntry((x, y, z, biome) -> {
|
||||
int cy = y >> 2;
|
||||
if (cy < minSection || cy >= maxSection) {
|
||||
return;
|
||||
}
|
||||
|
||||
var chunk = (LevelChunk) world.getChunk(x >> 2, z >> 2, ChunkStatus.FULL, false);
|
||||
if (chunk == null) return;
|
||||
|
||||
var section = chunk.getSection(cy - minSection);
|
||||
PalettedContainer<Holder<Biome>> container = (PalettedContainer<Holder<Biome>>) section.getBiomes();
|
||||
|
||||
var holder = registry.getHolder(biome);
|
||||
if (holder.isPresent()) {
|
||||
container.set(x & 3, y & 3, z & 3, holder.get());
|
||||
changedChunks.add(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
var chunkMap = world.getChunkSource().chunkMap;
|
||||
HashMap<ServerPlayer, List<LevelChunk>> map = new HashMap<>();
|
||||
for (LevelChunk chunk : changedChunks) {
|
||||
chunk.setUnsaved(true);
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
for (ServerPlayer serverPlayer2 : chunkMap.getPlayers(chunkPos, false)) {
|
||||
map.computeIfAbsent(serverPlayer2, serverPlayer -> new ArrayList<>()).add(chunk);
|
||||
}
|
||||
biomeBuffer.forEachEntry((x, y, z, biome) -> {
|
||||
int cy = y >> 2;
|
||||
if (cy < minSection || cy >= maxSection) {
|
||||
return;
|
||||
}
|
||||
|
||||
var chunk = (LevelChunk) world.getChunk(x >> 2, z >> 2, ChunkStatus.FULL, false);
|
||||
if (chunk == null) return;
|
||||
|
||||
var section = chunk.getSection(cy - minSection);
|
||||
PalettedContainer<Holder<Biome>> container = (PalettedContainer<Holder<Biome>>) section.getBiomes();
|
||||
|
||||
var holder = registry.getHolder(biome);
|
||||
if (holder.isPresent()) {
|
||||
container.set(x & 3, y & 3, z & 3, holder.get());
|
||||
changedChunks.add(chunk);
|
||||
}
|
||||
map.forEach((serverPlayer, list) -> serverPlayer.connection.send(ClientboundChunksBiomesPacket.forChunks(list)));
|
||||
});
|
||||
|
||||
var chunkMap = world.getChunkSource().chunkMap;
|
||||
HashMap<ServerPlayer, List<LevelChunk>> map = new HashMap<>();
|
||||
for (LevelChunk chunk : changedChunks) {
|
||||
chunk.setUnsaved(true);
|
||||
ChunkPos chunkPos = chunk.getPos();
|
||||
for (ServerPlayer serverPlayer2 : chunkMap.getPlayers(chunkPos, false)) {
|
||||
map.computeIfAbsent(serverPlayer2, serverPlayer -> new ArrayList<>()).add(chunk);
|
||||
}
|
||||
}
|
||||
map.forEach((serverPlayer, list) -> serverPlayer.connection.send(ClientboundChunksBiomesPacket.forChunks(list)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.AxiomPaper;
|
||||
import com.moulberry.axiom.event.AxiomModifyWorldEvent;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import com.moulberry.axiom.integration.VersionTranslator;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
@ -19,23 +19,18 @@ import net.minecraft.world.level.lighting.LightEngine;
|
||||
import org.bukkit.Bukkit;
|
||||
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;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class SetBlockPacketListener implements PluginMessageListener {
|
||||
public class SetBlockPacketListener implements AxiomPacketListener {
|
||||
|
||||
private final AxiomPaper plugin;
|
||||
private final Method updateBlockEntityTicker;
|
||||
|
||||
public SetBlockPacketListener(AxiomPaper plugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
public SetBlockPacketListener() {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
String methodName = reflectionRemapper.remapMethodName(LevelChunk.class, "updateBlockEntityTicker", BlockEntity.class);
|
||||
|
||||
@ -49,20 +44,16 @@ public class SetBlockPacketListener implements PluginMessageListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player bukkitPlayer, @NotNull byte[] message) {
|
||||
if (!bukkitPlayer.hasPermission("axiom.*")) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void onMessage(@NotNull Player bukkitPlayer, @NotNull ByteBuf buf) {
|
||||
// Check if player is allowed to modify this world
|
||||
AxiomModifyWorldEvent modifyWorldEvent = new AxiomModifyWorldEvent(bukkitPlayer, bukkitPlayer.getWorld());
|
||||
Bukkit.getPluginManager().callEvent(modifyWorldEvent);
|
||||
if (modifyWorldEvent.isCancelled()) return;
|
||||
|
||||
// Read packet
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message));
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
BlockPos blockPos = friendlyByteBuf.readBlockPos();
|
||||
BlockState blockState = friendlyByteBuf.readById(Block.BLOCK_STATE_REGISTRY);
|
||||
BlockState blockState = Block.BLOCK_STATE_REGISTRY.byId(VersionTranslator.impl.blockStateMapper(bukkitPlayer).apply(friendlyByteBuf.readVarInt()));
|
||||
boolean updateNeighbors = friendlyByteBuf.readBoolean();
|
||||
int sequenceId = friendlyByteBuf.readInt();
|
||||
|
||||
|
@ -3,26 +3,21 @@ package com.moulberry.axiom.packet;
|
||||
import com.moulberry.axiom.AxiomConstants;
|
||||
import com.moulberry.axiom.View;
|
||||
import com.moulberry.axiom.persistence.UUIDDataType;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SetEditorViewsPacketListener implements PluginMessageListener {
|
||||
public class SetEditorViewsPacketListener implements AxiomPacketListener {
|
||||
|
||||
@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));
|
||||
public void onMessage(@NotNull Player player, @NotNull ByteBuf buf) {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
UUID uuid = friendlyByteBuf.readUUID();
|
||||
List<View> views = friendlyByteBuf.readList(View::read);
|
||||
|
||||
|
@ -1,28 +1,17 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.event.AxiomFlySpeedChangeEvent;
|
||||
import com.moulberry.axiom.event.AxiomGameModeChangeEvent;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
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 SetFlySpeedPacketListener implements PluginMessageListener {
|
||||
public class SetFlySpeedPacketListener implements AxiomPacketListener {
|
||||
|
||||
@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));
|
||||
float flySpeed = friendlyByteBuf.readFloat();
|
||||
public void onMessage(@NotNull Player player, @NotNull ByteBuf buf) {
|
||||
float flySpeed = buf.readFloat();
|
||||
|
||||
// Call event
|
||||
AxiomFlySpeedChangeEvent flySpeedChangeEvent = new AxiomFlySpeedChangeEvent(player, flySpeed);
|
||||
|
@ -1,34 +1,26 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.event.AxiomGameModeChangeEvent;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
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 SetGamemodePacketListener implements PluginMessageListener {
|
||||
public class SetGamemodePacketListener implements AxiomPacketListener {
|
||||
|
||||
@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));
|
||||
GameType gameType = GameType.byId(friendlyByteBuf.readByte());
|
||||
public void onMessage(Player player, ByteBuf buf) {
|
||||
@SuppressWarnings("deprecation")
|
||||
GameMode gameMode = GameMode.getByValue(buf.readByte());
|
||||
assert gameMode != null;
|
||||
|
||||
// Call event
|
||||
AxiomGameModeChangeEvent gameModeChangeEvent = new AxiomGameModeChangeEvent(player, GameMode.getByValue(gameType.getId()));
|
||||
AxiomGameModeChangeEvent gameModeChangeEvent = new AxiomGameModeChangeEvent(player, gameMode);
|
||||
Bukkit.getPluginManager().callEvent(gameModeChangeEvent);
|
||||
if (gameModeChangeEvent.isCancelled()) return;
|
||||
|
||||
// Change gamemode
|
||||
((CraftPlayer)player).getHandle().setGameMode(gameType);
|
||||
player.setGameMode(gameMode);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,26 +2,20 @@ package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.AxiomConstants;
|
||||
import com.moulberry.axiom.persistence.ItemStackDataType;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SetHotbarSlotPacketListener implements PluginMessageListener {
|
||||
public class SetHotbarSlotPacketListener implements AxiomPacketListener {
|
||||
|
||||
@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));
|
||||
public void onMessage(@NotNull Player player, @NotNull ByteBuf buf) {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
int index = friendlyByteBuf.readByte();
|
||||
if (index < 0 || index >= 9*9) return;
|
||||
net.minecraft.world.item.ItemStack nmsStack = friendlyByteBuf.readItem();
|
||||
|
@ -2,7 +2,7 @@ package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.AxiomConstants;
|
||||
import com.moulberry.axiom.persistence.ItemStackDataType;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
@ -12,18 +12,13 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SwitchActiveHotbarPacketListener implements PluginMessageListener {
|
||||
public class SwitchActiveHotbarPacketListener implements AxiomPacketListener {
|
||||
|
||||
@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));
|
||||
public void onMessage(@NotNull Player player, @NotNull ByteBuf buf) {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
int oldHotbarIndex = friendlyByteBuf.readByte();
|
||||
int activeHotbarIndex = friendlyByteBuf.readByte();
|
||||
|
||||
|
@ -1,26 +1,23 @@
|
||||
package com.moulberry.axiom.packet;
|
||||
|
||||
import com.moulberry.axiom.event.AxiomGameModeChangeEvent;
|
||||
import com.moulberry.axiom.event.AxiomTeleportEvent;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TeleportPacketListener implements PluginMessageListener {
|
||||
public class TeleportPacketListener implements AxiomPacketListener {
|
||||
|
||||
@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));
|
||||
public void onMessage(@NotNull Player player, @NotNull ByteBuf buf) {
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(buf);
|
||||
ResourceKey<Level> resourceKey = friendlyByteBuf.readResourceKey(Registries.DIMENSION);
|
||||
double x = friendlyByteBuf.readDouble();
|
||||
double y = friendlyByteBuf.readDouble();
|
||||
|
@ -2,8 +2,12 @@ name: $name
|
||||
version: $version
|
||||
main: com.moulberry.axiom.AxiomPaper
|
||||
description: $description
|
||||
softdepend:
|
||||
- ViaVersion
|
||||
- WorldGuard
|
||||
authors:
|
||||
- Moulberry
|
||||
- Lixfel
|
||||
api-version: "$apiVersion"
|
||||
permissions:
|
||||
axiom.*:
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren