Mirror von
https://github.com/Moulberry/AxiomPaperPlugin.git
synchronisiert 2024-11-13 19:50:09 +01:00
Support annotations, add more restrictions, improve version detection
Dieser Commit ist enthalten in:
Ursprung
54e780a6db
Commit
3481216653
@ -8,7 +8,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "com.moulberry.axiom"
|
group = "com.moulberry.axiom"
|
||||||
version = "1.5.12"
|
version = "3.3.0"
|
||||||
description = "Serverside component for Axiom on Paper"
|
description = "Serverside component for Axiom on Paper"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
@ -12,7 +12,7 @@ public class AxiomConstants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int API_VERSION = 7;
|
public static final int API_VERSION = 8;
|
||||||
public static final NamespacedKey ACTIVE_HOTBAR_INDEX = new NamespacedKey("axiom", "active_hotbar_index");
|
public static final NamespacedKey ACTIVE_HOTBAR_INDEX = new NamespacedKey("axiom", "active_hotbar_index");
|
||||||
public static final NamespacedKey HOTBAR_DATA = new NamespacedKey("axiom", "hotbar_data");
|
public static final NamespacedKey HOTBAR_DATA = new NamespacedKey("axiom", "hotbar_data");
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
|||||||
private boolean logLargeBlockBufferChanges = false;
|
private boolean logLargeBlockBufferChanges = false;
|
||||||
|
|
||||||
public Path blueprintFolder = null;
|
public Path blueprintFolder = null;
|
||||||
|
public boolean allowAnnotations = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
@ -87,6 +88,11 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
|||||||
List<String> disallowedBlocks = this.configuration.getStringList("disallowed-blocks");
|
List<String> disallowedBlocks = this.configuration.getStringList("disallowed-blocks");
|
||||||
this.allowedBlockRegistry = DisallowedBlocks.createAllowedBlockRegistry(disallowedBlocks);
|
this.allowedBlockRegistry = DisallowedBlocks.createAllowedBlockRegistry(disallowedBlocks);
|
||||||
|
|
||||||
|
this.allowAnnotations = this.configuration.getBoolean("allow-annotations");
|
||||||
|
|
||||||
|
int allowedCapabilities = calculateAllowedCapabilities();
|
||||||
|
int infiniteReachLimit = this.configuration.getInt("infinite-reach-limit");
|
||||||
|
|
||||||
Bukkit.getPluginManager().registerEvents(this, this);
|
Bukkit.getPluginManager().registerEvents(this, this);
|
||||||
// Bukkit.getPluginManager().registerEvents(new WorldPropertiesExample(), this);
|
// Bukkit.getPluginManager().registerEvents(new WorldPropertiesExample(), this);
|
||||||
CompressedBlockEntity.initialize(this);
|
CompressedBlockEntity.initialize(this);
|
||||||
@ -103,6 +109,7 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
|||||||
msg.registerOutgoingPluginChannel(this, "axiom:restrictions");
|
msg.registerOutgoingPluginChannel(this, "axiom:restrictions");
|
||||||
msg.registerOutgoingPluginChannel(this, "axiom:marker_data");
|
msg.registerOutgoingPluginChannel(this, "axiom:marker_data");
|
||||||
msg.registerOutgoingPluginChannel(this, "axiom:marker_nbt_response");
|
msg.registerOutgoingPluginChannel(this, "axiom:marker_nbt_response");
|
||||||
|
msg.registerOutgoingPluginChannel(this, "axiom:annotation_update");
|
||||||
|
|
||||||
if (configuration.getBoolean("packet-handlers.hello")) {
|
if (configuration.getBoolean("packet-handlers.hello")) {
|
||||||
msg.registerIncomingPluginChannel(this, "axiom:hello", new HelloPacketListener(this));
|
msg.registerIncomingPluginChannel(this, "axiom:hello", new HelloPacketListener(this));
|
||||||
@ -158,6 +165,7 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
|||||||
if (configuration.getBoolean("packet-handlers.set-buffer")) {
|
if (configuration.getBoolean("packet-handlers.set-buffer")) {
|
||||||
SetBlockBufferPacketListener setBlockBufferPacketListener = new SetBlockBufferPacketListener(this);
|
SetBlockBufferPacketListener setBlockBufferPacketListener = new SetBlockBufferPacketListener(this);
|
||||||
UploadBlueprintPacketListener uploadBlueprintPacketListener = new UploadBlueprintPacketListener(this);
|
UploadBlueprintPacketListener uploadBlueprintPacketListener = new UploadBlueprintPacketListener(this);
|
||||||
|
UpdateAnnotationPacketListener updateAnnotationPacketListener = new UpdateAnnotationPacketListener(this);
|
||||||
RequestChunkDataPacketListener requestChunkDataPacketListener = allowLargeChunkDataRequest ?
|
RequestChunkDataPacketListener requestChunkDataPacketListener = allowLargeChunkDataRequest ?
|
||||||
new RequestChunkDataPacketListener(this) : null;
|
new RequestChunkDataPacketListener(this) : null;
|
||||||
|
|
||||||
@ -179,7 +187,7 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
|||||||
Connection connection = (Connection) channel.pipeline().get("packet_handler");
|
Connection connection = (Connection) channel.pipeline().get("packet_handler");
|
||||||
channel.pipeline().addBefore("decoder", "axiom-big-payload-handler",
|
channel.pipeline().addBefore("decoder", "axiom-big-payload-handler",
|
||||||
new AxiomBigPayloadHandler(payloadId, connection, setBlockBufferPacketListener,
|
new AxiomBigPayloadHandler(payloadId, connection, setBlockBufferPacketListener,
|
||||||
uploadBlueprintPacketListener, requestChunkDataPacketListener));
|
uploadBlueprintPacketListener, updateAnnotationPacketListener, requestChunkDataPacketListener));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -252,12 +260,19 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean allowImportingBlocks = player.hasPermission("axiom.can_import_blocks");
|
boolean allowImportingBlocks = player.hasPermission("axiom.can_import_blocks");
|
||||||
|
boolean canCreateAnnotations = this.allowAnnotations && player.hasPermission("axiom.annotation.create");
|
||||||
|
|
||||||
if (restrictions.maxSectionsPerSecond != rateLimit ||
|
if (restrictions.maxSectionsPerSecond != rateLimit ||
|
||||||
restrictions.canImportBlocks != allowImportingBlocks ||
|
restrictions.canImportBlocks != allowImportingBlocks ||
|
||||||
|
restrictions.canCreateAnnotations != canCreateAnnotations ||
|
||||||
|
restrictions.allowedCapabilities != allowedCapabilities ||
|
||||||
|
restrictions.infiniteReachLimit != infiniteReachLimit ||
|
||||||
!Objects.equals(restrictions.bounds, bounds)) {
|
!Objects.equals(restrictions.bounds, bounds)) {
|
||||||
restrictions.maxSectionsPerSecond = rateLimit;
|
restrictions.maxSectionsPerSecond = rateLimit;
|
||||||
restrictions.canImportBlocks = allowImportingBlocks;
|
restrictions.canImportBlocks = allowImportingBlocks;
|
||||||
|
restrictions.canCreateAnnotations = canCreateAnnotations;
|
||||||
|
restrictions.allowedCapabilities = allowedCapabilities;
|
||||||
|
restrictions.infiniteReachLimit = infiniteReachLimit;
|
||||||
restrictions.bounds = bounds;
|
restrictions.bounds = bounds;
|
||||||
send = true;
|
send = true;
|
||||||
}
|
}
|
||||||
@ -302,6 +317,25 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int calculateAllowedCapabilities() {
|
||||||
|
Set<String> allowed = new HashSet<>(this.configuration.getStringList("allow-capabilities"));
|
||||||
|
if (allowed.contains("all")) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int allowedCapabilities = 0;
|
||||||
|
if (allowed.contains("bulldozer")) allowedCapabilities |= Restrictions.ALLOW_BULLDOZER;
|
||||||
|
if (allowed.contains("replace_mode")) allowedCapabilities |= Restrictions.ALLOW_REPLACE_MODE;
|
||||||
|
if (allowed.contains("force_place")) allowedCapabilities |= Restrictions.ALLOW_FORCE_PLACE;
|
||||||
|
if (allowed.contains("no_updates")) allowedCapabilities |= Restrictions.ALLOW_NO_UPDATES;
|
||||||
|
if (allowed.contains("tinker")) allowedCapabilities |= Restrictions.ALLOW_TINKER;
|
||||||
|
if (allowed.contains("infinite_reach")) allowedCapabilities |= Restrictions.ALLOW_INFINITE_REACH;
|
||||||
|
if (allowed.contains("fast_place")) allowedCapabilities |= Restrictions.ALLOW_FAST_PLACE;
|
||||||
|
if (allowed.contains("angel_placement")) allowedCapabilities |= Restrictions.ALLOW_ANGEL_PLACEMENT;
|
||||||
|
if (allowed.contains("no_clip")) allowedCapabilities |= Restrictions.ALLOW_NO_CLIP;
|
||||||
|
return allowedCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean logLargeBlockBufferChanges() {
|
public boolean logLargeBlockBufferChanges() {
|
||||||
return this.logLargeBlockBufferChanges;
|
return this.logLargeBlockBufferChanges;
|
||||||
}
|
}
|
||||||
|
@ -10,61 +10,76 @@ import java.util.Set;
|
|||||||
|
|
||||||
public class Restrictions {
|
public class Restrictions {
|
||||||
|
|
||||||
|
public static final int ALLOW_BULLDOZER = 1;
|
||||||
|
public static final int ALLOW_REPLACE_MODE = 2;
|
||||||
|
public static final int ALLOW_FORCE_PLACE = 4;
|
||||||
|
public static final int ALLOW_NO_UPDATES = 8;
|
||||||
|
public static final int ALLOW_TINKER = 16;
|
||||||
|
public static final int ALLOW_INFINITE_REACH = 32;
|
||||||
|
public static final int ALLOW_FAST_PLACE = 64;
|
||||||
|
public static final int ALLOW_ANGEL_PLACEMENT = 128;
|
||||||
|
public static final int ALLOW_NO_CLIP = 256;
|
||||||
|
public static final int ALLOW_ALL = -1;
|
||||||
|
|
||||||
public boolean canImportBlocks = true;
|
public boolean canImportBlocks = true;
|
||||||
public boolean canUseEditor = true;
|
public boolean canUseEditor = true;
|
||||||
public boolean canEditDisplayEntities = true;
|
public boolean canEditDisplayEntities = true;
|
||||||
|
public boolean canCreateAnnotations = false;
|
||||||
|
public int allowedCapabilities = ALLOW_ALL;
|
||||||
|
public int infiniteReachLimit = -1;
|
||||||
|
|
||||||
public int maxSectionsPerSecond = 0;
|
public int maxSectionsPerSecond = 0;
|
||||||
public Set<PlotSquaredIntegration.PlotBox> bounds = Set.of();
|
public Set<PlotSquaredIntegration.PlotBox> bounds = Set.of();
|
||||||
|
|
||||||
public PlotSquaredIntegration.PlotBounds lastPlotBounds = null;
|
public PlotSquaredIntegration.PlotBounds lastPlotBounds = null;
|
||||||
|
|
||||||
public void send(AxiomPaper plugin, Player player) {
|
public void send(AxiomPaper plugin, Player player) {
|
||||||
if (player.getListeningPluginChannels().contains("axiom:restrictions")) {
|
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
buf.writeBoolean(this.canImportBlocks);
|
||||||
buf.writeBoolean(this.canImportBlocks);
|
buf.writeBoolean(this.canUseEditor);
|
||||||
buf.writeBoolean(this.canUseEditor);
|
buf.writeBoolean(this.canEditDisplayEntities);
|
||||||
buf.writeBoolean(this.canEditDisplayEntities);
|
buf.writeBoolean(this.canCreateAnnotations);
|
||||||
|
buf.writeInt(this.allowedCapabilities);
|
||||||
|
buf.writeInt(this.infiniteReachLimit);
|
||||||
|
|
||||||
buf.writeVarInt(this.maxSectionsPerSecond);
|
buf.writeVarInt(this.maxSectionsPerSecond);
|
||||||
|
|
||||||
int count = Math.min(64, bounds.size());
|
int count = Math.min(64, bounds.size());
|
||||||
buf.writeVarInt(count);
|
buf.writeVarInt(count);
|
||||||
for (PlotSquaredIntegration.PlotBox bound : this.bounds) {
|
for (PlotSquaredIntegration.PlotBox bound : this.bounds) {
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
count -= 1;
|
count -= 1;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
int minX = bound.min().getX();
|
|
||||||
int minY = bound.min().getY();
|
|
||||||
int minZ = bound.min().getZ();
|
|
||||||
int maxX = bound.max().getX();
|
|
||||||
int maxY = bound.max().getY();
|
|
||||||
int maxZ = bound.max().getZ();
|
|
||||||
|
|
||||||
if (minX < -33554431) minX = -33554431;
|
|
||||||
if (minX > 33554431) minX = 33554431;
|
|
||||||
if (minY < -2047) minY = -2047;
|
|
||||||
if (minY > 2047) minY = 2047;
|
|
||||||
if (minZ < -33554431) minZ = -33554431;
|
|
||||||
if (minZ > 33554431) minZ = 33554431;
|
|
||||||
|
|
||||||
if (maxX < -33554431) maxX = -33554431;
|
|
||||||
if (maxX > 33554431) maxX = 33554431;
|
|
||||||
if (maxY < -2047) maxY = -2047;
|
|
||||||
if (maxY > 2047) maxY = 2047;
|
|
||||||
if (maxZ < -33554431) maxZ = -33554431;
|
|
||||||
if (maxZ > 33554431) maxZ = 33554431;
|
|
||||||
|
|
||||||
buf.writeBlockPos(new BlockPos(minX, minY, minZ));
|
|
||||||
buf.writeBlockPos(new BlockPos(maxX, maxY, maxZ));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] bytes = new byte[buf.writerIndex()];
|
int minX = bound.min().getX();
|
||||||
buf.getBytes(0, bytes);
|
int minY = bound.min().getY();
|
||||||
player.sendPluginMessage(plugin, "axiom:restrictions", bytes);
|
int minZ = bound.min().getZ();
|
||||||
|
int maxX = bound.max().getX();
|
||||||
|
int maxY = bound.max().getY();
|
||||||
|
int maxZ = bound.max().getZ();
|
||||||
|
|
||||||
|
if (minX < -33554431) minX = -33554431;
|
||||||
|
if (minX > 33554431) minX = 33554431;
|
||||||
|
if (minY < -2047) minY = -2047;
|
||||||
|
if (minY > 2047) minY = 2047;
|
||||||
|
if (minZ < -33554431) minZ = -33554431;
|
||||||
|
if (minZ > 33554431) minZ = 33554431;
|
||||||
|
|
||||||
|
if (maxX < -33554431) maxX = -33554431;
|
||||||
|
if (maxX > 33554431) maxX = 33554431;
|
||||||
|
if (maxY < -2047) maxY = -2047;
|
||||||
|
if (maxY > 2047) maxY = 2047;
|
||||||
|
if (maxZ < -33554431) maxZ = -33554431;
|
||||||
|
if (maxZ > 33554431) maxZ = 33554431;
|
||||||
|
|
||||||
|
buf.writeBlockPos(new BlockPos(minX, minY, minZ));
|
||||||
|
buf.writeBlockPos(new BlockPos(maxX, maxY, maxZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] bytes = new byte[buf.writerIndex()];
|
||||||
|
buf.getBytes(0, bytes);
|
||||||
|
player.sendPluginMessage(plugin, "axiom:restrictions", bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.moulberry.axiom;
|
package com.moulberry.axiom;
|
||||||
|
|
||||||
|
import com.moulberry.axiom.annotations.ServerAnnotations;
|
||||||
import com.moulberry.axiom.marker.MarkerData;
|
import com.moulberry.axiom.marker.MarkerData;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import it.unimi.dsi.fastutil.longs.*;
|
import it.unimi.dsi.fastutil.longs.*;
|
||||||
@ -35,6 +36,10 @@ public class WorldExtension {
|
|||||||
public static void onPlayerJoin(World world, Player player) {
|
public static void onPlayerJoin(World world, Player player) {
|
||||||
ServerLevel level = ((CraftWorld)world).getHandle();
|
ServerLevel level = ((CraftWorld)world).getHandle();
|
||||||
get(level).onPlayerJoin(player);
|
get(level).onPlayerJoin(player);
|
||||||
|
|
||||||
|
if (AxiomPaper.PLUGIN.canUseAxiom(player, "axiom.annotations.view")) {
|
||||||
|
ServerAnnotations.sendAll(world, ((CraftPlayer)player).getHandle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tick(MinecraftServer server, boolean sendMarkers, int maxChunkRelightsPerTick, int maxChunkSendsPerTick) {
|
public static void tick(MinecraftServer server, boolean sendMarkers, int maxChunkRelightsPerTick, int maxChunkSendsPerTick) {
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
package com.moulberry.axiom.annotations;
|
||||||
|
|
||||||
|
import com.moulberry.axiom.annotations.data.AnnotationData;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface AnnotationUpdateAction {
|
||||||
|
|
||||||
|
void write(FriendlyByteBuf friendlyByteBuf);
|
||||||
|
|
||||||
|
static AnnotationUpdateAction read(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
byte type = friendlyByteBuf.readByte();
|
||||||
|
if (type == 0) {
|
||||||
|
UUID uuid = friendlyByteBuf.readUUID();
|
||||||
|
AnnotationData annotationData = AnnotationData.read(friendlyByteBuf);
|
||||||
|
if (annotationData == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new CreateAnnotation(uuid, annotationData);
|
||||||
|
} else if (type == 1) {
|
||||||
|
return new DeleteAnnotation(friendlyByteBuf.readUUID());
|
||||||
|
} else if (type == 2) {
|
||||||
|
return new MoveAnnotation(friendlyByteBuf.readUUID(), new Vector3f(
|
||||||
|
friendlyByteBuf.readFloat(),
|
||||||
|
friendlyByteBuf.readFloat(),
|
||||||
|
friendlyByteBuf.readFloat()
|
||||||
|
));
|
||||||
|
} else if (type == 3) {
|
||||||
|
return new ClearAllAnnotations();
|
||||||
|
} else if (type == 4) {
|
||||||
|
return new RotateAnnotation(friendlyByteBuf.readUUID(), new Quaternionf(
|
||||||
|
friendlyByteBuf.readFloat(),
|
||||||
|
friendlyByteBuf.readFloat(),
|
||||||
|
friendlyByteBuf.readFloat(),
|
||||||
|
friendlyByteBuf.readFloat()
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record CreateAnnotation(UUID uuid, AnnotationData annotationData) implements AnnotationUpdateAction {
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(0);
|
||||||
|
friendlyByteBuf.writeUUID(this.uuid);
|
||||||
|
this.annotationData.write(friendlyByteBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record DeleteAnnotation(UUID uuid) implements AnnotationUpdateAction {
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(1);
|
||||||
|
friendlyByteBuf.writeUUID(this.uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record MoveAnnotation(UUID uuid, Vector3f to) implements AnnotationUpdateAction {
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(2);
|
||||||
|
friendlyByteBuf.writeUUID(this.uuid);
|
||||||
|
friendlyByteBuf.writeFloat(this.to.x);
|
||||||
|
friendlyByteBuf.writeFloat(this.to.y);
|
||||||
|
friendlyByteBuf.writeFloat(this.to.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
record ClearAllAnnotations() implements AnnotationUpdateAction {
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
record RotateAnnotation(UUID uuid, Quaternionf to) implements AnnotationUpdateAction {
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(4);
|
||||||
|
friendlyByteBuf.writeUUID(this.uuid);
|
||||||
|
friendlyByteBuf.writeFloat(this.to.x);
|
||||||
|
friendlyByteBuf.writeFloat(this.to.y);
|
||||||
|
friendlyByteBuf.writeFloat(this.to.z);
|
||||||
|
friendlyByteBuf.writeFloat(this.to.w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
136
src/main/java/com/moulberry/axiom/annotations/ServerAnnotations.java
Normale Datei
136
src/main/java/com/moulberry/axiom/annotations/ServerAnnotations.java
Normale Datei
@ -0,0 +1,136 @@
|
|||||||
|
package com.moulberry.axiom.annotations;
|
||||||
|
|
||||||
|
import com.moulberry.axiom.AxiomPaper;
|
||||||
|
import com.moulberry.axiom.VersionHelper;
|
||||||
|
import com.moulberry.axiom.annotations.data.AnnotationData;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.util.datafix.DataFixTypes;
|
||||||
|
import net.minecraft.world.level.saveddata.SavedData;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||||
|
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
public class ServerAnnotations {
|
||||||
|
|
||||||
|
private static final WeakHashMap<World, ServerAnnotations> serverAnnotationCache = new WeakHashMap<>();
|
||||||
|
private static final NamespacedKey ANNOTATION_DATA_KEY = new NamespacedKey(AxiomPaper.PLUGIN, "annotation_data");
|
||||||
|
|
||||||
|
final LinkedHashMap<UUID, AnnotationData> annotations = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
private static void sendAnnotationUpdates(List<AnnotationUpdateAction> actions, List<ServerPlayer> players) {
|
||||||
|
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||||
|
friendlyByteBuf.writeCollection(actions, (buffer, action) -> action.write(buffer));
|
||||||
|
|
||||||
|
byte[] bytes = new byte[friendlyByteBuf.writerIndex()];
|
||||||
|
friendlyByteBuf.getBytes(0, bytes);
|
||||||
|
for (ServerPlayer serverPlayer : players) {
|
||||||
|
VersionHelper.sendCustomPayload(serverPlayer, VersionHelper.createResourceLocation("axiom:annotation_update"), bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendAll(World world, ServerPlayer player) {
|
||||||
|
if (!AxiomPaper.PLUGIN.allowAnnotations) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AnnotationUpdateAction> actions = new ArrayList<>();
|
||||||
|
|
||||||
|
actions.add(new AnnotationUpdateAction.ClearAllAnnotations());
|
||||||
|
|
||||||
|
ServerAnnotations serverAnnotations = serverAnnotationCache.get(world);
|
||||||
|
if (serverAnnotations == null) {
|
||||||
|
serverAnnotations = world.getPersistentDataContainer().get(ANNOTATION_DATA_KEY, ServerAnnotationsAdapater.INSTANCE);
|
||||||
|
serverAnnotationCache.put(world, serverAnnotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverAnnotations != null) {
|
||||||
|
for (Map.Entry<UUID, AnnotationData> entry : serverAnnotations.annotations.entrySet()) {
|
||||||
|
actions.add(new AnnotationUpdateAction.CreateAnnotation(entry.getKey(), entry.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendAnnotationUpdates(actions, List.of(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleUpdates(World world, List<AnnotationUpdateAction> actions) {
|
||||||
|
if (!AxiomPaper.PLUGIN.allowAnnotations) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerAnnotations serverAnnotations = serverAnnotationCache.get(world);
|
||||||
|
if (serverAnnotations == null) {
|
||||||
|
serverAnnotations = world.getPersistentDataContainer().get(ANNOTATION_DATA_KEY, ServerAnnotationsAdapater.INSTANCE);
|
||||||
|
serverAnnotationCache.put(world, serverAnnotations);
|
||||||
|
}
|
||||||
|
if (serverAnnotations == null) {
|
||||||
|
serverAnnotations = new ServerAnnotations();
|
||||||
|
serverAnnotationCache.put(world, serverAnnotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean dirty = false;
|
||||||
|
|
||||||
|
for (AnnotationUpdateAction action : actions) {
|
||||||
|
if (action instanceof AnnotationUpdateAction.CreateAnnotation create) {
|
||||||
|
serverAnnotations.annotations.put(create.uuid(), create.annotationData());
|
||||||
|
dirty = true;
|
||||||
|
} else if (action instanceof AnnotationUpdateAction.DeleteAnnotation delete) {
|
||||||
|
AnnotationData removed = serverAnnotations.annotations.remove(delete.uuid());
|
||||||
|
if (removed != null) {
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
} else if (action instanceof AnnotationUpdateAction.MoveAnnotation move) {
|
||||||
|
AnnotationData annotation = serverAnnotations.annotations.get(move.uuid());
|
||||||
|
if (annotation != null) {
|
||||||
|
annotation.setPosition(move.to());
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
} else if (action instanceof AnnotationUpdateAction.ClearAllAnnotations) {
|
||||||
|
if (!serverAnnotations.annotations.isEmpty()) {
|
||||||
|
serverAnnotations.annotations.clear();
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
} else if (action instanceof AnnotationUpdateAction.RotateAnnotation rotate) {
|
||||||
|
AnnotationData annotation = serverAnnotations.annotations.get(rotate.uuid());
|
||||||
|
if (annotation != null) {
|
||||||
|
annotation.setRotation(rotate.to());
|
||||||
|
dirty = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("Unknown action: " + action.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirty) {
|
||||||
|
world.getPersistentDataContainer().set(ANNOTATION_DATA_KEY, ServerAnnotationsAdapater.INSTANCE, serverAnnotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward actions back to clients
|
||||||
|
List<ServerPlayer> playersWithAxiom = new ArrayList<>();
|
||||||
|
|
||||||
|
for (ServerPlayer player : ((CraftWorld)world).getHandle().players()) {
|
||||||
|
if (AxiomPaper.PLUGIN.canUseAxiom(player.getBukkitEntity(), "axiom.annotations.view")) {
|
||||||
|
playersWithAxiom.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!playersWithAxiom.isEmpty()) {
|
||||||
|
sendAnnotationUpdates(actions, playersWithAxiom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package com.moulberry.axiom.annotations;
|
||||||
|
|
||||||
|
import com.moulberry.axiom.AxiomPaper;
|
||||||
|
import com.moulberry.axiom.annotations.data.AnnotationData;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ServerAnnotationsAdapater implements PersistentDataType<PersistentDataContainer, ServerAnnotations> {
|
||||||
|
public static final ServerAnnotationsAdapater INSTANCE = new ServerAnnotationsAdapater();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Class<PersistentDataContainer> getPrimitiveType() {
|
||||||
|
return PersistentDataContainer.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Class<ServerAnnotations> getComplexType() {
|
||||||
|
return ServerAnnotations.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull PersistentDataContainer toPrimitive(@NotNull ServerAnnotations serverAnnotations, @NotNull PersistentDataAdapterContext context) {
|
||||||
|
PersistentDataContainer container = context.newPersistentDataContainer();
|
||||||
|
|
||||||
|
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.buffer());
|
||||||
|
|
||||||
|
for (Map.Entry<UUID, AnnotationData> entry : serverAnnotations.annotations.entrySet()) {
|
||||||
|
try {
|
||||||
|
friendlyByteBuf.writerIndex(0);
|
||||||
|
entry.getValue().write(friendlyByteBuf);
|
||||||
|
|
||||||
|
byte[] bytes = new byte[friendlyByteBuf.writerIndex()];
|
||||||
|
friendlyByteBuf.getBytes(0, bytes);
|
||||||
|
|
||||||
|
container.set(new NamespacedKey(AxiomPaper.PLUGIN, entry.getKey().toString()),
|
||||||
|
PersistentDataType.BYTE_ARRAY, bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ServerAnnotations fromPrimitive(@NotNull PersistentDataContainer container, @NotNull PersistentDataAdapterContext context) {
|
||||||
|
ServerAnnotations serverAnnotations = new ServerAnnotations();
|
||||||
|
|
||||||
|
for (NamespacedKey key : container.getKeys()) {
|
||||||
|
try {
|
||||||
|
String uuidString = key.value();
|
||||||
|
UUID uuid = UUID.fromString(uuidString);
|
||||||
|
|
||||||
|
byte[] bytes = container.get(key, PersistentDataType.BYTE_ARRAY);
|
||||||
|
AnnotationData annotation = AnnotationData.read(new FriendlyByteBuf(Unpooled.wrappedBuffer(bytes)));
|
||||||
|
|
||||||
|
serverAnnotations.annotations.put(uuid, annotation);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return serverAnnotations;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.moulberry.axiom.annotations.data;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
public interface AnnotationData {
|
||||||
|
|
||||||
|
void setPosition(Vector3f position);
|
||||||
|
void setRotation(Quaternionf rotation);
|
||||||
|
void write(FriendlyByteBuf friendlyByteBuf);
|
||||||
|
|
||||||
|
static AnnotationData read(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
byte type = friendlyByteBuf.readByte();
|
||||||
|
if (type == 0) {
|
||||||
|
return LineAnnotationData.read(friendlyByteBuf);
|
||||||
|
} else if (type == 1) {
|
||||||
|
return TextAnnotationData.read(friendlyByteBuf);
|
||||||
|
} else if (type == 2) {
|
||||||
|
return ImageAnnotationData.read(friendlyByteBuf);
|
||||||
|
} else if (type == 3) {
|
||||||
|
return FreehandOutlineAnnotationData.read(friendlyByteBuf);
|
||||||
|
} else if (type == 4) {
|
||||||
|
return LinesOutlineAnnotationData.read(friendlyByteBuf);
|
||||||
|
} else if (type == 5) {
|
||||||
|
return BoxOutlineAnnotationData.read(friendlyByteBuf);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.moulberry.axiom.annotations.data;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
public record BoxOutlineAnnotationData(int fromX, int fromY, int fromZ, int toX, int toY, int toZ, int colour) implements AnnotationData {
|
||||||
|
|
||||||
|
public BoxOutlineAnnotationData {
|
||||||
|
colour = 0xFF000000 | colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(Vector3f position) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRotation(Quaternionf rotation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(5);
|
||||||
|
friendlyByteBuf.writeVarInt(this.fromX);
|
||||||
|
friendlyByteBuf.writeVarInt(this.fromY);
|
||||||
|
friendlyByteBuf.writeVarInt(this.fromZ);
|
||||||
|
friendlyByteBuf.writeVarInt(this.toX);
|
||||||
|
friendlyByteBuf.writeVarInt(this.toY);
|
||||||
|
friendlyByteBuf.writeVarInt(this.toZ);
|
||||||
|
friendlyByteBuf.writeInt(this.colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BoxOutlineAnnotationData read(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
int fromX = friendlyByteBuf.readVarInt();
|
||||||
|
int fromY = friendlyByteBuf.readVarInt();
|
||||||
|
int fromZ = friendlyByteBuf.readVarInt();
|
||||||
|
int toX = friendlyByteBuf.readVarInt();
|
||||||
|
int toY = friendlyByteBuf.readVarInt();
|
||||||
|
int toZ = friendlyByteBuf.readVarInt();
|
||||||
|
int colour = friendlyByteBuf.readInt();
|
||||||
|
return new BoxOutlineAnnotationData(fromX, fromY, fromZ, toX, toY, toZ, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.moulberry.axiom.annotations.data;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
public record FreehandOutlineAnnotationData(BlockPos start, byte[] offsets, int offsetCount, int colour) implements AnnotationData {
|
||||||
|
|
||||||
|
public FreehandOutlineAnnotationData {
|
||||||
|
colour = 0xFF000000 | colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(Vector3f position) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRotation(Quaternionf rotation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(3);
|
||||||
|
friendlyByteBuf.writeVarInt(this.start.getX());
|
||||||
|
friendlyByteBuf.writeVarInt(this.start.getY());
|
||||||
|
friendlyByteBuf.writeVarInt(this.start.getZ());
|
||||||
|
friendlyByteBuf.writeVarInt(this.offsetCount);
|
||||||
|
friendlyByteBuf.writeInt(this.colour);
|
||||||
|
friendlyByteBuf.writeByteArray(this.offsets);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FreehandOutlineAnnotationData read(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
int x = friendlyByteBuf.readVarInt();
|
||||||
|
int y = friendlyByteBuf.readVarInt();
|
||||||
|
int z = friendlyByteBuf.readVarInt();
|
||||||
|
int offsetCount = friendlyByteBuf.readVarInt();
|
||||||
|
int colour = friendlyByteBuf.readInt();
|
||||||
|
byte[] offsets = friendlyByteBuf.readByteArray();
|
||||||
|
return new FreehandOutlineAnnotationData(new BlockPos(x, y, z), offsets, offsetCount, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.moulberry.axiom.annotations.data;
|
||||||
|
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
public record ImageAnnotationData(String imageUrl, Vector3f position, Quaternionf rotation, Direction direction, float fallbackYaw, float width, int billboardMode) implements AnnotationData {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(Vector3f position) {
|
||||||
|
this.position.set(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRotation(Quaternionf rotation) {
|
||||||
|
this.rotation.set(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(2);
|
||||||
|
friendlyByteBuf.writeUtf(this.imageUrl);
|
||||||
|
friendlyByteBuf.writeFloat(this.position.x);
|
||||||
|
friendlyByteBuf.writeFloat(this.position.y);
|
||||||
|
friendlyByteBuf.writeFloat(this.position.z);
|
||||||
|
friendlyByteBuf.writeFloat(this.rotation.x);
|
||||||
|
friendlyByteBuf.writeFloat(this.rotation.y);
|
||||||
|
friendlyByteBuf.writeFloat(this.rotation.z);
|
||||||
|
friendlyByteBuf.writeFloat(this.rotation.w);
|
||||||
|
friendlyByteBuf.writeByte(this.direction.get3DDataValue());
|
||||||
|
friendlyByteBuf.writeFloat(this.fallbackYaw);
|
||||||
|
friendlyByteBuf.writeFloat(this.width);
|
||||||
|
friendlyByteBuf.writeByte(this.billboardMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImageAnnotationData read(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
String imageUrl = friendlyByteBuf.readUtf();
|
||||||
|
float x = friendlyByteBuf.readFloat();
|
||||||
|
float y = friendlyByteBuf.readFloat();
|
||||||
|
float z = friendlyByteBuf.readFloat();
|
||||||
|
float rotX = friendlyByteBuf.readFloat();
|
||||||
|
float rotY = friendlyByteBuf.readFloat();
|
||||||
|
float rotZ = friendlyByteBuf.readFloat();
|
||||||
|
float rotW = friendlyByteBuf.readFloat();
|
||||||
|
Direction direction = Direction.from3DDataValue(friendlyByteBuf.readByte());
|
||||||
|
float fallbackYaw = friendlyByteBuf.readFloat();
|
||||||
|
float width = friendlyByteBuf.readFloat();
|
||||||
|
int billboardMode = friendlyByteBuf.readByte();
|
||||||
|
return new ImageAnnotationData(imageUrl, new Vector3f(x, y, z), new Quaternionf(rotX, rotY, rotZ, rotW), direction, fallbackYaw, width, billboardMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.moulberry.axiom.annotations.data;
|
||||||
|
|
||||||
|
import net.minecraft.core.Vec3i;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
public record LineAnnotationData(Vec3i startQuantized, byte[] offsets, float lineWidth, int colour) implements AnnotationData {
|
||||||
|
|
||||||
|
public LineAnnotationData {
|
||||||
|
colour = 0xFF000000 | colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(Vector3f position) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRotation(Quaternionf rotation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(0);
|
||||||
|
friendlyByteBuf.writeVarInt(this.startQuantized.getX());
|
||||||
|
friendlyByteBuf.writeVarInt(this.startQuantized.getY());
|
||||||
|
friendlyByteBuf.writeVarInt(this.startQuantized.getZ());
|
||||||
|
friendlyByteBuf.writeFloat(this.lineWidth);
|
||||||
|
friendlyByteBuf.writeInt(this.colour);
|
||||||
|
friendlyByteBuf.writeByteArray(this.offsets);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LineAnnotationData read(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
int x = friendlyByteBuf.readVarInt();
|
||||||
|
int y = friendlyByteBuf.readVarInt();
|
||||||
|
int z = friendlyByteBuf.readVarInt();
|
||||||
|
float lineWidth = friendlyByteBuf.readFloat();
|
||||||
|
int colour = friendlyByteBuf.readInt();
|
||||||
|
byte[] offsets = friendlyByteBuf.readByteArray();
|
||||||
|
return new LineAnnotationData(new Vec3i(x, y, z), offsets, lineWidth, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.moulberry.axiom.annotations.data;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
public record LinesOutlineAnnotationData(long[] positions, int colour) implements AnnotationData {
|
||||||
|
|
||||||
|
public LinesOutlineAnnotationData {
|
||||||
|
colour = 0xFF000000 | colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(Vector3f position) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRotation(Quaternionf rotation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(4);
|
||||||
|
friendlyByteBuf.writeVarInt(this.positions.length);
|
||||||
|
for (long position : this.positions) {
|
||||||
|
friendlyByteBuf.writeLong(position);
|
||||||
|
}
|
||||||
|
friendlyByteBuf.writeInt(this.colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LinesOutlineAnnotationData read(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
int positionCount = friendlyByteBuf.readVarInt();
|
||||||
|
long[] positions = new long[positionCount];
|
||||||
|
for (int i = 0; i < positionCount; i++) {
|
||||||
|
positions[i] = friendlyByteBuf.readLong();
|
||||||
|
}
|
||||||
|
int colour = friendlyByteBuf.readInt();
|
||||||
|
return new LinesOutlineAnnotationData(positions, colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.moulberry.axiom.annotations.data;
|
||||||
|
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
public record TextAnnotationData(String text, Vector3f position, Quaternionf rotation, Direction direction, float fallbackYaw, float scale,
|
||||||
|
int billboardMode, int colour, boolean shadow) implements AnnotationData {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(Vector3f position) {
|
||||||
|
this.position.set(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRotation(Quaternionf rotation) {
|
||||||
|
this.rotation.set(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
friendlyByteBuf.writeByte(1);
|
||||||
|
friendlyByteBuf.writeUtf(this.text);
|
||||||
|
friendlyByteBuf.writeFloat(this.position.x);
|
||||||
|
friendlyByteBuf.writeFloat(this.position.y);
|
||||||
|
friendlyByteBuf.writeFloat(this.position.z);
|
||||||
|
friendlyByteBuf.writeFloat(this.rotation.x);
|
||||||
|
friendlyByteBuf.writeFloat(this.rotation.y);
|
||||||
|
friendlyByteBuf.writeFloat(this.rotation.z);
|
||||||
|
friendlyByteBuf.writeFloat(this.rotation.w);
|
||||||
|
friendlyByteBuf.writeByte(this.direction.get3DDataValue());
|
||||||
|
friendlyByteBuf.writeFloat(this.fallbackYaw);
|
||||||
|
friendlyByteBuf.writeFloat(this.scale);
|
||||||
|
friendlyByteBuf.writeByte(this.billboardMode);
|
||||||
|
friendlyByteBuf.writeInt(this.colour);
|
||||||
|
friendlyByteBuf.writeBoolean(this.shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TextAnnotationData read(FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
String text = friendlyByteBuf.readUtf();
|
||||||
|
float x = friendlyByteBuf.readFloat();
|
||||||
|
float y = friendlyByteBuf.readFloat();
|
||||||
|
float z = friendlyByteBuf.readFloat();
|
||||||
|
float rotX = friendlyByteBuf.readFloat();
|
||||||
|
float rotY = friendlyByteBuf.readFloat();
|
||||||
|
float rotZ = friendlyByteBuf.readFloat();
|
||||||
|
float rotW = friendlyByteBuf.readFloat();
|
||||||
|
Direction direction = Direction.from3DDataValue(friendlyByteBuf.readByte());
|
||||||
|
float fallbackYaw = friendlyByteBuf.readFloat();
|
||||||
|
float scale = friendlyByteBuf.readFloat();
|
||||||
|
int billboardMode = friendlyByteBuf.readByte();
|
||||||
|
int colour = friendlyByteBuf.readInt();
|
||||||
|
boolean shadow = friendlyByteBuf.readBoolean();
|
||||||
|
return new TextAnnotationData(text, new Vector3f(x, y, z), new Quaternionf(rotX, rotY, rotZ, rotW), direction, fallbackYaw, scale, billboardMode, colour, shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,19 +20,23 @@ public class AxiomBigPayloadHandler extends MessageToMessageDecoder<ByteBuf> {
|
|||||||
|
|
||||||
private static final ResourceLocation SET_BUFFER = VersionHelper.createResourceLocation("axiom", "set_buffer");
|
private static final ResourceLocation SET_BUFFER = VersionHelper.createResourceLocation("axiom", "set_buffer");
|
||||||
private static final ResourceLocation UPLOAD_BLUEPRINT = VersionHelper.createResourceLocation("axiom", "upload_blueprint");
|
private static final ResourceLocation UPLOAD_BLUEPRINT = VersionHelper.createResourceLocation("axiom", "upload_blueprint");
|
||||||
|
private static final ResourceLocation UPDATE_ANNOTATIONS = VersionHelper.createResourceLocation("axiom", "annotation_update");
|
||||||
private static final ResourceLocation REQUEST_CHUNK_DATA = VersionHelper.createResourceLocation("axiom", "request_chunk_data");
|
private static final ResourceLocation REQUEST_CHUNK_DATA = VersionHelper.createResourceLocation("axiom", "request_chunk_data");
|
||||||
private final int payloadId;
|
private final int payloadId;
|
||||||
private final Connection connection;
|
private final Connection connection;
|
||||||
private final SetBlockBufferPacketListener setBlockBuffer;
|
private final SetBlockBufferPacketListener setBlockBuffer;
|
||||||
private final UploadBlueprintPacketListener uploadBlueprint;
|
private final UploadBlueprintPacketListener uploadBlueprint;
|
||||||
|
private final UpdateAnnotationPacketListener updateAnnotation;
|
||||||
private final RequestChunkDataPacketListener requestChunkDataPacketListener;
|
private final RequestChunkDataPacketListener requestChunkDataPacketListener;
|
||||||
|
|
||||||
public AxiomBigPayloadHandler(int payloadId, Connection connection, SetBlockBufferPacketListener setBlockBuffer,
|
public AxiomBigPayloadHandler(int payloadId, Connection connection, SetBlockBufferPacketListener setBlockBuffer,
|
||||||
UploadBlueprintPacketListener uploadBlueprint, RequestChunkDataPacketListener requestChunkDataPacketListener) {
|
UploadBlueprintPacketListener uploadBlueprint, UpdateAnnotationPacketListener updateAnnotation,
|
||||||
|
RequestChunkDataPacketListener requestChunkDataPacketListener) {
|
||||||
this.payloadId = payloadId;
|
this.payloadId = payloadId;
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.setBlockBuffer = setBlockBuffer;
|
this.setBlockBuffer = setBlockBuffer;
|
||||||
this.uploadBlueprint = uploadBlueprint;
|
this.uploadBlueprint = uploadBlueprint;
|
||||||
|
this.updateAnnotation = updateAnnotation;
|
||||||
this.requestChunkDataPacketListener = requestChunkDataPacketListener;
|
this.requestChunkDataPacketListener = requestChunkDataPacketListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +84,14 @@ public class AxiomBigPayloadHandler extends MessageToMessageDecoder<ByteBuf> {
|
|||||||
" bytes extra whilst reading packet");
|
" bytes extra whilst reading packet");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
} else if (identifier.equals(UPDATE_ANNOTATIONS)) {
|
||||||
|
updateAnnotation.onReceive(player, buf);
|
||||||
|
success = true;
|
||||||
|
if (in.readableBytes() > 0) {
|
||||||
|
throw new IOException("Axiom packet " + identifier + " was larger than I expected, found " + in.readableBytes() +
|
||||||
|
" bytes extra whilst reading packet");
|
||||||
|
}
|
||||||
|
return;
|
||||||
} else if (requestChunkDataPacketListener != null && identifier.equals(REQUEST_CHUNK_DATA)) {
|
} else if (requestChunkDataPacketListener != null && identifier.equals(REQUEST_CHUNK_DATA)) {
|
||||||
byte[] bytes = new byte[buf.writerIndex() - buf.readerIndex()];
|
byte[] bytes = new byte[buf.writerIndex() - buf.readerIndex()];
|
||||||
buf.getBytes(buf.readerIndex(), bytes);
|
buf.getBytes(buf.readerIndex(), bytes);
|
||||||
@ -122,7 +134,7 @@ public class AxiomBigPayloadHandler extends MessageToMessageDecoder<ByteBuf> {
|
|||||||
if (evt == ConnectionEvent.COMPRESSION_THRESHOLD_SET || evt == ConnectionEvent.COMPRESSION_DISABLED) {
|
if (evt == ConnectionEvent.COMPRESSION_THRESHOLD_SET || evt == ConnectionEvent.COMPRESSION_DISABLED) {
|
||||||
ctx.channel().pipeline().remove("axiom-big-payload-handler");
|
ctx.channel().pipeline().remove("axiom-big-payload-handler");
|
||||||
ctx.channel().pipeline().addBefore("decoder", "axiom-big-payload-handler",
|
ctx.channel().pipeline().addBefore("decoder", "axiom-big-payload-handler",
|
||||||
new AxiomBigPayloadHandler(payloadId, connection, setBlockBuffer, uploadBlueprint, requestChunkDataPacketListener));
|
new AxiomBigPayloadHandler(payloadId, connection, setBlockBuffer, uploadBlueprint, updateAnnotation, requestChunkDataPacketListener));
|
||||||
}
|
}
|
||||||
super.userEventTriggered(ctx, evt);
|
super.userEventTriggered(ctx, evt);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.moulberry.axiom.packet;
|
|||||||
|
|
||||||
import com.google.common.util.concurrent.RateLimiter;
|
import com.google.common.util.concurrent.RateLimiter;
|
||||||
import com.moulberry.axiom.*;
|
import com.moulberry.axiom.*;
|
||||||
|
import com.moulberry.axiom.annotations.ServerAnnotations;
|
||||||
import com.moulberry.axiom.blueprint.ServerBlueprintManager;
|
import com.moulberry.axiom.blueprint.ServerBlueprintManager;
|
||||||
import com.moulberry.axiom.event.AxiomHandshakeEvent;
|
import com.moulberry.axiom.event.AxiomHandshakeEvent;
|
||||||
import com.moulberry.axiom.persistence.ItemStackDataType;
|
import com.moulberry.axiom.persistence.ItemStackDataType;
|
||||||
@ -20,6 +21,7 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
|
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -49,13 +51,6 @@ public class HelloPacketListener implements PluginMessageListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int normalizeDataVersion(int dataVersion) {
|
|
||||||
if (dataVersion == 3955) { // 1.21.1
|
|
||||||
return 3953; // 1.21
|
|
||||||
}
|
|
||||||
return dataVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void process(Player player, byte[] message) {
|
private void process(Player player, byte[] message) {
|
||||||
if (!this.plugin.hasAxiomPermission(player)) {
|
if (!this.plugin.hasAxiomPermission(player)) {
|
||||||
return;
|
return;
|
||||||
@ -63,11 +58,32 @@ public class HelloPacketListener implements PluginMessageListener {
|
|||||||
|
|
||||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message));
|
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message));
|
||||||
int apiVersion = friendlyByteBuf.readVarInt();
|
int apiVersion = friendlyByteBuf.readVarInt();
|
||||||
|
|
||||||
|
if (apiVersion != AxiomConstants.API_VERSION) {
|
||||||
|
String versions = " (C="+apiVersion+" S="+AxiomConstants.API_VERSION+")";
|
||||||
|
Component text;
|
||||||
|
if (apiVersion < AxiomConstants.API_VERSION) {
|
||||||
|
text = Component.text("Unable to use Axiom, you're on an outdated version! Please update to the latest version of Axiom to use it on this server." + versions);
|
||||||
|
} else {
|
||||||
|
text = Component.text("Unable to use Axiom, server hasn't updated Axiom yet." + versions);
|
||||||
|
}
|
||||||
|
|
||||||
|
String unsupportedAxiomVersion = plugin.configuration.getString("unsupported-axiom-version");
|
||||||
|
if (unsupportedAxiomVersion == null) unsupportedAxiomVersion = "kick";
|
||||||
|
if (unsupportedAxiomVersion.equals("warn")) {
|
||||||
|
player.sendMessage(text.color(NamedTextColor.RED));
|
||||||
|
return;
|
||||||
|
} else if (!unsupportedAxiomVersion.equals("ignore")) {
|
||||||
|
player.kick(text);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int dataVersion = friendlyByteBuf.readVarInt();
|
int dataVersion = friendlyByteBuf.readVarInt();
|
||||||
// note - skipping NBT here. friendlyByteBuf.readNBT();
|
int protocolVersion = friendlyByteBuf.readVarInt();
|
||||||
|
|
||||||
int serverDataVersion = SharedConstants.getCurrentVersion().getDataVersion().getVersion();
|
int serverDataVersion = SharedConstants.getCurrentVersion().getDataVersion().getVersion();
|
||||||
if (normalizeDataVersion(dataVersion) != normalizeDataVersion(serverDataVersion)) {
|
if (protocolVersion != SharedConstants.getProtocolVersion()) {
|
||||||
String incompatibleDataVersion = plugin.configuration.getString("incompatible-data-version");
|
String incompatibleDataVersion = plugin.configuration.getString("incompatible-data-version");
|
||||||
if (incompatibleDataVersion == null) incompatibleDataVersion = "warn";
|
if (incompatibleDataVersion == null) incompatibleDataVersion = "warn";
|
||||||
|
|
||||||
@ -83,35 +99,11 @@ public class HelloPacketListener implements PluginMessageListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int playerVersion = Via.getAPI().getPlayerVersion(player.getUniqueId());
|
|
||||||
if (playerVersion == SharedConstants.getProtocolVersion()) {
|
|
||||||
// Likely using via on the proxy, try to get protocol version from data version
|
|
||||||
if (dataVersion < 3337) {
|
|
||||||
player.sendMessage(incompatibleWarning.color(NamedTextColor.RED));
|
|
||||||
return;
|
|
||||||
} else if (dataVersion == 3337) {
|
|
||||||
playerVersion = 762; // 1.19.4
|
|
||||||
} else if (dataVersion <= 3465) {
|
|
||||||
playerVersion = 763; // 1.20.1
|
|
||||||
} else if (dataVersion <= 3578) {
|
|
||||||
playerVersion = 764; // 1.20.2
|
|
||||||
} else if (dataVersion <= 3700) {
|
|
||||||
playerVersion = 765; // 1.20.3 / 1.20.4
|
|
||||||
} else if (dataVersion <= 3839) {
|
|
||||||
playerVersion = 766; // 1.20.5 / 1.20.6
|
|
||||||
} else if (dataVersion <= 3955) {
|
|
||||||
playerVersion = 767; // 1.21.1
|
|
||||||
} else {
|
|
||||||
player.sendMessage(incompatibleWarning.color(NamedTextColor.RED));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IdMapper<BlockState> mapper;
|
IdMapper<BlockState> mapper;
|
||||||
try {
|
try {
|
||||||
mapper = ViaVersionHelper.getBlockRegistryForVersion(this.plugin.allowedBlockRegistry, playerVersion);
|
mapper = ViaVersionHelper.getBlockRegistryForVersion(this.plugin.allowedBlockRegistry, protocolVersion);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String clientDescription = "client: " + ProtocolVersion.getProtocol(playerVersion);
|
String clientDescription = "client: " + ProtocolVersion.getProtocol(protocolVersion);
|
||||||
String serverDescription = "server: " + ProtocolVersion.getProtocol(SharedConstants.getProtocolVersion());
|
String serverDescription = "server: " + ProtocolVersion.getProtocol(SharedConstants.getProtocolVersion());
|
||||||
String description = clientDescription + " <-> " + serverDescription;
|
String description = clientDescription + " <-> " + serverDescription;
|
||||||
Component text = Component.text("Axiom+ViaVersion: " + e.getMessage() + " (" + description + ")");
|
Component text = Component.text("Axiom+ViaVersion: " + e.getMessage() + " (" + description + ")");
|
||||||
@ -125,7 +117,7 @@ public class HelloPacketListener implements PluginMessageListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.plugin.playerBlockRegistry.put(player.getUniqueId(), mapper);
|
this.plugin.playerBlockRegistry.put(player.getUniqueId(), mapper);
|
||||||
this.plugin.playerProtocolVersion.put(player.getUniqueId(), playerVersion);
|
this.plugin.playerProtocolVersion.put(player.getUniqueId(), protocolVersion);
|
||||||
|
|
||||||
Component text = Component.text("Axiom: Warning, client and server versions don't match. " +
|
Component text = Component.text("Axiom: Warning, client and server versions don't match. " +
|
||||||
"Axiom will try to use ViaVersion conversions, but this process may cause problems");
|
"Axiom will try to use ViaVersion conversions, but this process may cause problems");
|
||||||
@ -133,35 +125,6 @@ public class HelloPacketListener implements PluginMessageListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apiVersion != AxiomConstants.API_VERSION) {
|
|
||||||
Component text = Component.text("Unsupported Axiom API Version. Server supports " + AxiomConstants.API_VERSION +
|
|
||||||
", while client is " + apiVersion);
|
|
||||||
|
|
||||||
String unsupportedAxiomVersion = plugin.configuration.getString("unsupported-axiom-version");
|
|
||||||
if (unsupportedAxiomVersion == null) unsupportedAxiomVersion = "kick";
|
|
||||||
if (unsupportedAxiomVersion.equals("warn")) {
|
|
||||||
player.sendMessage(text.color(NamedTextColor.RED));
|
|
||||||
return;
|
|
||||||
} else if (!unsupportedAxiomVersion.equals("ignore")) {
|
|
||||||
player.kick(text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.getListeningPluginChannels().contains("axiom:restrictions")) {
|
|
||||||
Component text = Component.text("This server requires the use of Axiom 2.3 or later. Contact the server administrator if you believe this is unintentional");
|
|
||||||
|
|
||||||
String unsupportedRestrictions = plugin.configuration.getString("client-doesnt-support-restrictions");
|
|
||||||
if (unsupportedRestrictions == null) unsupportedRestrictions = "warn";
|
|
||||||
if (unsupportedRestrictions.equals("warn")) {
|
|
||||||
player.sendMessage(text.color(NamedTextColor.RED));
|
|
||||||
return;
|
|
||||||
} else if (!unsupportedRestrictions.equals("ignore")) {
|
|
||||||
player.kick(text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call handshake event
|
// Call handshake event
|
||||||
int maxBufferSize = plugin.configuration.getInt("max-block-buffer-packet-size");
|
int maxBufferSize = plugin.configuration.getInt("max-block-buffer-packet-size");
|
||||||
AxiomHandshakeEvent handshakeEvent = new AxiomHandshakeEvent(player, maxBufferSize);
|
AxiomHandshakeEvent handshakeEvent = new AxiomHandshakeEvent(player, maxBufferSize);
|
||||||
|
@ -33,10 +33,16 @@ import net.minecraft.world.phys.Vec3;
|
|||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
|
||||||
|
import org.bukkit.craftbukkit.v1_20_R3.block.CapturedBlockState;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock;
|
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock;
|
||||||
|
import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockStates;
|
||||||
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
|
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
|
||||||
|
import org.bukkit.craftbukkit.v1_20_R3.event.CraftEventFactory;
|
||||||
|
import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -44,6 +50,8 @@ import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
|||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -107,6 +115,8 @@ public class SetBlockPacketListener implements PluginMessageListener {
|
|||||||
player.connection.ackBlockChangesUpTo(sequenceId);
|
player.connection.ackBlockChangesUpTo(sequenceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlockPlaceContext blockPlaceContext = new BlockPlaceContext(player, hand, player.getItemInHand(hand), blockHit);
|
||||||
|
|
||||||
if (!blockHit.getLocation().equals(Vec3.ZERO)) {
|
if (!blockHit.getLocation().equals(Vec3.ZERO)) {
|
||||||
org.bukkit.inventory.ItemStack heldItem;
|
org.bukkit.inventory.ItemStack heldItem;
|
||||||
if (hand == InteractionHand.MAIN_HAND) {
|
if (hand == InteractionHand.MAIN_HAND) {
|
||||||
@ -126,12 +136,30 @@ public class SetBlockPacketListener implements PluginMessageListener {
|
|||||||
if (!playerInteractEvent.callEvent()) {
|
if (!playerInteractEvent.callEvent()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call BlockMultiPlace / BlockPlace event
|
||||||
|
List<org.bukkit.block.BlockState> blockStates = new ArrayList<>();
|
||||||
|
for (Map.Entry<BlockPos, BlockState> entry : blocks.entrySet()) {
|
||||||
|
blockStates.add(CraftBlockStates.getBlockState(entry.getKey(), entry.getValue(), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
Cancellable event = null;
|
||||||
|
if (blockStates.size() > 1) {
|
||||||
|
event = CraftEventFactory.callBlockMultiPlaceEvent(player.serverLevel(),
|
||||||
|
player, hand, blockStates, blockHit.getBlockPos().getX(),
|
||||||
|
blockHit.getBlockPos().getY(), blockHit.getBlockPos().getZ());
|
||||||
|
} else if (blockStates.size() == 1) {
|
||||||
|
event = CraftEventFactory.callBlockPlaceEvent(player.serverLevel(),
|
||||||
|
player, hand, blockStates.get(0), blockHit.getBlockPos().getX(),
|
||||||
|
blockHit.getBlockPos().getY(), blockHit.getBlockPos().getZ());
|
||||||
|
}
|
||||||
|
if (event != null && event.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CraftWorld world = player.level().getWorld();
|
CraftWorld world = player.level().getWorld();
|
||||||
|
|
||||||
BlockPlaceContext blockPlaceContext = new BlockPlaceContext(player, hand, player.getItemInHand(hand), blockHit);
|
|
||||||
|
|
||||||
// Update blocks
|
// Update blocks
|
||||||
if (updateNeighbors) {
|
if (updateNeighbors) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.moulberry.axiom.packet;
|
||||||
|
|
||||||
|
import com.moulberry.axiom.AxiomPaper;
|
||||||
|
import com.moulberry.axiom.annotations.AnnotationUpdateAction;
|
||||||
|
import com.moulberry.axiom.annotations.ServerAnnotations;
|
||||||
|
import com.moulberry.axiom.blueprint.BlueprintIo;
|
||||||
|
import com.moulberry.axiom.blueprint.RawBlueprint;
|
||||||
|
import com.moulberry.axiom.blueprint.ServerBlueprintManager;
|
||||||
|
import com.moulberry.axiom.blueprint.ServerBlueprintRegistry;
|
||||||
|
import net.minecraft.SharedConstants;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UpdateAnnotationPacketListener {
|
||||||
|
|
||||||
|
private final AxiomPaper plugin;
|
||||||
|
public UpdateAnnotationPacketListener(AxiomPaper plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onReceive(ServerPlayer serverPlayer, FriendlyByteBuf friendlyByteBuf) {
|
||||||
|
if (!this.plugin.allowAnnotations || !this.plugin.canUseAxiom(serverPlayer.getBukkitEntity(), "axiom.annotation.create")) {
|
||||||
|
friendlyByteBuf.writerIndex(friendlyByteBuf.readerIndex());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read actions
|
||||||
|
int length = friendlyByteBuf.readVarInt();
|
||||||
|
List<AnnotationUpdateAction> actions = new ArrayList<>(Math.min(256, length));
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
AnnotationUpdateAction action = AnnotationUpdateAction.read(friendlyByteBuf);
|
||||||
|
if (action != null) {
|
||||||
|
actions.add(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
serverPlayer.getServer().execute(() -> {
|
||||||
|
try {
|
||||||
|
ServerAnnotations.handleUpdates(serverPlayer.serverLevel().getWorld(), actions);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
serverPlayer.getBukkitEntity().kick(net.kyori.adventure.text.Component.text(
|
||||||
|
"An error occured while updating annotations: " + t.getMessage()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,6 +25,7 @@ public class UploadBlueprintPacketListener {
|
|||||||
|
|
||||||
public void onReceive(ServerPlayer serverPlayer, FriendlyByteBuf friendlyByteBuf) {
|
public void onReceive(ServerPlayer serverPlayer, FriendlyByteBuf friendlyByteBuf) {
|
||||||
if (!this.plugin.canUseAxiom(serverPlayer.getBukkitEntity(), "axiom.blueprint.upload")) {
|
if (!this.plugin.canUseAxiom(serverPlayer.getBukkitEntity(), "axiom.blueprint.upload")) {
|
||||||
|
friendlyByteBuf.writerIndex(friendlyByteBuf.readerIndex());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,12 +18,10 @@ blueprint-sharing: false
|
|||||||
allow-large-chunk-data-request: false
|
allow-large-chunk-data-request: false
|
||||||
|
|
||||||
# Action to take when a user with an incompatible Minecraft version or Axiom version joins
|
# Action to take when a user with an incompatible Minecraft version or Axiom version joins
|
||||||
# Valid actions are 'kick', 'warn' and 'ignore'
|
# Valid actions are 'kick' and 'warn'
|
||||||
# 'warn' will give the player a warning and disable Axiom
|
# 'warn' will give the player a warning and disable Axiom
|
||||||
# Using 'ignore' may result in corruption and is only provided for debugging purposes
|
|
||||||
incompatible-data-version: "warn"
|
incompatible-data-version: "warn"
|
||||||
unsupported-axiom-version: "warn"
|
unsupported-axiom-version: "warn"
|
||||||
client-doesnt-support-restrictions: "ignore"
|
|
||||||
|
|
||||||
# Maximum packet size. Must not be less than 32767
|
# Maximum packet size. Must not be less than 32767
|
||||||
max-block-buffer-packet-size: 0x100000
|
max-block-buffer-packet-size: 0x100000
|
||||||
@ -59,11 +57,28 @@ blacklist-entities:
|
|||||||
# True allows players to see/manipulate marker entities
|
# True allows players to see/manipulate marker entities
|
||||||
send-markers: false
|
send-markers: false
|
||||||
|
|
||||||
|
# True to enable Annotations on this server
|
||||||
|
allow-annotations: false
|
||||||
|
|
||||||
# Disallowed blocks
|
# Disallowed blocks
|
||||||
disallowed-blocks:
|
disallowed-blocks:
|
||||||
# - "minecraft:wheat"
|
# - "minecraft:wheat"
|
||||||
# - "minecraft:oak_stairs[waterlogged=true]"
|
# - "minecraft:oak_stairs[waterlogged=true]"
|
||||||
|
|
||||||
|
allow-capabilities:
|
||||||
|
- "all"
|
||||||
|
# - "bulldozer"
|
||||||
|
# - "replace_mode"
|
||||||
|
# - "force_place"
|
||||||
|
# - "no_updates"
|
||||||
|
# - "tinker"
|
||||||
|
# - "infinite_reach"
|
||||||
|
# - "fast_place"
|
||||||
|
# - "angel_placement"
|
||||||
|
# - "no_clip"
|
||||||
|
|
||||||
|
infinite-reach-limit: 256
|
||||||
|
|
||||||
# Toggles for individual packet handlers. May break certain features
|
# Toggles for individual packet handlers. May break certain features
|
||||||
packet-handlers:
|
packet-handlers:
|
||||||
hello: true
|
hello: true
|
||||||
|
@ -32,6 +32,12 @@ permissions:
|
|||||||
axiom.blueprint.upload: true
|
axiom.blueprint.upload: true
|
||||||
axiom.blueprint.request: true
|
axiom.blueprint.request: true
|
||||||
axiom.blueprint.manifest: true
|
axiom.blueprint.manifest: true
|
||||||
|
axiom.annotation.*:
|
||||||
|
description: Allows creating and viewing annotations
|
||||||
|
default: op
|
||||||
|
children:
|
||||||
|
axiom.annotation.create: true
|
||||||
|
axiom.annotation.view: true
|
||||||
axiom.chunk.*:
|
axiom.chunk.*:
|
||||||
description: Allows use of all chunk-related features
|
description: Allows use of all chunk-related features
|
||||||
default: op
|
default: op
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren