Mirror von
https://github.com/Moulberry/AxiomPaperPlugin.git
synchronisiert 2024-11-09 01:50:05 +01:00
Support annotations, add more restrictions, improve version detection
Dieser Commit ist enthalten in:
Ursprung
ba97f1d132
Commit
f3ab70eb23
@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "com.moulberry.axiom"
|
||||
version = "1.5.12"
|
||||
version = "3.3.0"
|
||||
description = "Serverside component for Axiom on Paper"
|
||||
|
||||
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 HOTBAR_DATA = new NamespacedKey("axiom", "hotbar_data");
|
||||
|
||||
|
@ -65,6 +65,7 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
||||
private boolean logLargeBlockBufferChanges = false;
|
||||
|
||||
public Path blueprintFolder = null;
|
||||
public boolean allowAnnotations = false;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
@ -87,6 +88,11 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
||||
List<String> disallowedBlocks = this.configuration.getStringList("disallowed-blocks");
|
||||
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(new WorldPropertiesExample(), this);
|
||||
CompressedBlockEntity.initialize(this);
|
||||
@ -103,6 +109,7 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:restrictions");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:marker_data");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:marker_nbt_response");
|
||||
msg.registerOutgoingPluginChannel(this, "axiom:annotation_update");
|
||||
|
||||
if (configuration.getBoolean("packet-handlers.hello")) {
|
||||
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")) {
|
||||
SetBlockBufferPacketListener setBlockBufferPacketListener = new SetBlockBufferPacketListener(this);
|
||||
UploadBlueprintPacketListener uploadBlueprintPacketListener = new UploadBlueprintPacketListener(this);
|
||||
UpdateAnnotationPacketListener updateAnnotationPacketListener = new UpdateAnnotationPacketListener(this);
|
||||
RequestChunkDataPacketListener requestChunkDataPacketListener = allowLargeChunkDataRequest ?
|
||||
new RequestChunkDataPacketListener(this) : null;
|
||||
|
||||
@ -174,7 +182,7 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
||||
Connection connection = (Connection) channel.pipeline().get("packet_handler");
|
||||
channel.pipeline().addBefore("decoder", "axiom-big-payload-handler",
|
||||
new AxiomBigPayloadHandler(payloadId, connection, setBlockBufferPacketListener,
|
||||
uploadBlueprintPacketListener, requestChunkDataPacketListener));
|
||||
uploadBlueprintPacketListener, updateAnnotationPacketListener, requestChunkDataPacketListener));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -247,12 +255,19 @@ public class AxiomPaper extends JavaPlugin implements Listener {
|
||||
}
|
||||
|
||||
boolean allowImportingBlocks = player.hasPermission("axiom.can_import_blocks");
|
||||
boolean canCreateAnnotations = this.allowAnnotations && player.hasPermission("axiom.annotation.create");
|
||||
|
||||
if (restrictions.maxSectionsPerSecond != rateLimit ||
|
||||
restrictions.canImportBlocks != allowImportingBlocks ||
|
||||
restrictions.canCreateAnnotations != canCreateAnnotations ||
|
||||
restrictions.allowedCapabilities != allowedCapabilities ||
|
||||
restrictions.infiniteReachLimit != infiniteReachLimit ||
|
||||
!Objects.equals(restrictions.bounds, bounds)) {
|
||||
restrictions.maxSectionsPerSecond = rateLimit;
|
||||
restrictions.canImportBlocks = allowImportingBlocks;
|
||||
restrictions.canCreateAnnotations = canCreateAnnotations;
|
||||
restrictions.allowedCapabilities = allowedCapabilities;
|
||||
restrictions.infiniteReachLimit = infiniteReachLimit;
|
||||
restrictions.bounds = bounds;
|
||||
send = true;
|
||||
}
|
||||
@ -299,6 +314,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() {
|
||||
return this.logLargeBlockBufferChanges;
|
||||
}
|
||||
|
@ -10,61 +10,76 @@ import java.util.Set;
|
||||
|
||||
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 canUseEditor = true;
|
||||
public boolean canEditDisplayEntities = true;
|
||||
public boolean canCreateAnnotations = false;
|
||||
public int allowedCapabilities = ALLOW_ALL;
|
||||
public int infiniteReachLimit = -1;
|
||||
|
||||
public int maxSectionsPerSecond = 0;
|
||||
public Set<PlotSquaredIntegration.PlotBox> bounds = Set.of();
|
||||
|
||||
public PlotSquaredIntegration.PlotBounds lastPlotBounds = null;
|
||||
|
||||
public void send(AxiomPaper plugin, Player player) {
|
||||
if (player.getListeningPluginChannels().contains("axiom:restrictions")) {
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
buf.writeBoolean(this.canImportBlocks);
|
||||
buf.writeBoolean(this.canUseEditor);
|
||||
buf.writeBoolean(this.canEditDisplayEntities);
|
||||
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||
buf.writeBoolean(this.canImportBlocks);
|
||||
buf.writeBoolean(this.canUseEditor);
|
||||
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());
|
||||
buf.writeVarInt(count);
|
||||
for (PlotSquaredIntegration.PlotBox bound : this.bounds) {
|
||||
if (count > 0) {
|
||||
count -= 1;
|
||||
} else {
|
||||
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));
|
||||
int count = Math.min(64, bounds.size());
|
||||
buf.writeVarInt(count);
|
||||
for (PlotSquaredIntegration.PlotBox bound : this.bounds) {
|
||||
if (count > 0) {
|
||||
count -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[buf.writerIndex()];
|
||||
buf.getBytes(0, bytes);
|
||||
player.sendPluginMessage(plugin, "axiom:restrictions", bytes);
|
||||
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()];
|
||||
buf.getBytes(0, bytes);
|
||||
player.sendPluginMessage(plugin, "axiom:restrictions", bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.moulberry.axiom;
|
||||
|
||||
import com.moulberry.axiom.annotations.ServerAnnotations;
|
||||
import com.moulberry.axiom.marker.MarkerData;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.longs.*;
|
||||
@ -35,6 +36,10 @@ public class WorldExtension {
|
||||
public static void onPlayerJoin(World world, Player player) {
|
||||
ServerLevel level = ((CraftWorld)world).getHandle();
|
||||
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) {
|
||||
|
@ -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 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 final int payloadId;
|
||||
private final Connection connection;
|
||||
private final SetBlockBufferPacketListener setBlockBuffer;
|
||||
private final UploadBlueprintPacketListener uploadBlueprint;
|
||||
private final UpdateAnnotationPacketListener updateAnnotation;
|
||||
private final RequestChunkDataPacketListener requestChunkDataPacketListener;
|
||||
|
||||
public AxiomBigPayloadHandler(int payloadId, Connection connection, SetBlockBufferPacketListener setBlockBuffer,
|
||||
UploadBlueprintPacketListener uploadBlueprint, RequestChunkDataPacketListener requestChunkDataPacketListener) {
|
||||
UploadBlueprintPacketListener uploadBlueprint, UpdateAnnotationPacketListener updateAnnotation,
|
||||
RequestChunkDataPacketListener requestChunkDataPacketListener) {
|
||||
this.payloadId = payloadId;
|
||||
this.connection = connection;
|
||||
this.setBlockBuffer = setBlockBuffer;
|
||||
this.uploadBlueprint = uploadBlueprint;
|
||||
this.updateAnnotation = updateAnnotation;
|
||||
this.requestChunkDataPacketListener = requestChunkDataPacketListener;
|
||||
}
|
||||
|
||||
@ -80,6 +84,14 @@ public class AxiomBigPayloadHandler extends MessageToMessageDecoder<ByteBuf> {
|
||||
" bytes extra whilst reading packet");
|
||||
}
|
||||
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)) {
|
||||
byte[] bytes = new byte[buf.writerIndex() - buf.readerIndex()];
|
||||
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) {
|
||||
ctx.channel().pipeline().remove("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);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.moulberry.axiom.packet;
|
||||
|
||||
import com.google.common.util.concurrent.RateLimiter;
|
||||
import com.moulberry.axiom.*;
|
||||
import com.moulberry.axiom.annotations.ServerAnnotations;
|
||||
import com.moulberry.axiom.blueprint.ServerBlueprintManager;
|
||||
import com.moulberry.axiom.event.AxiomHandshakeEvent;
|
||||
import com.moulberry.axiom.persistence.ItemStackDataType;
|
||||
@ -22,6 +23,7 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -51,13 +53,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) {
|
||||
if (!this.plugin.hasAxiomPermission(player)) {
|
||||
return;
|
||||
@ -65,11 +60,32 @@ public class HelloPacketListener implements PluginMessageListener {
|
||||
|
||||
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message));
|
||||
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();
|
||||
// note - skipping NBT here. friendlyByteBuf.readNBT();
|
||||
int protocolVersion = friendlyByteBuf.readVarInt();
|
||||
|
||||
int serverDataVersion = SharedConstants.getCurrentVersion().getDataVersion().getVersion();
|
||||
if (normalizeDataVersion(dataVersion) != normalizeDataVersion(serverDataVersion)) {
|
||||
if (protocolVersion != SharedConstants.getProtocolVersion()) {
|
||||
String incompatibleDataVersion = plugin.configuration.getString("incompatible-data-version");
|
||||
if (incompatibleDataVersion == null) incompatibleDataVersion = "warn";
|
||||
|
||||
@ -85,35 +101,11 @@ public class HelloPacketListener implements PluginMessageListener {
|
||||
return;
|
||||
}
|
||||
} 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;
|
||||
try {
|
||||
mapper = ViaVersionHelper.getBlockRegistryForVersion(this.plugin.allowedBlockRegistry, playerVersion);
|
||||
mapper = ViaVersionHelper.getBlockRegistryForVersion(this.plugin.allowedBlockRegistry, protocolVersion);
|
||||
} catch (Exception e) {
|
||||
String clientDescription = "client: " + ProtocolVersion.getProtocol(playerVersion);
|
||||
String clientDescription = "client: " + ProtocolVersion.getProtocol(protocolVersion);
|
||||
String serverDescription = "server: " + ProtocolVersion.getProtocol(SharedConstants.getProtocolVersion());
|
||||
String description = clientDescription + " <-> " + serverDescription;
|
||||
Component text = Component.text("Axiom+ViaVersion: " + e.getMessage() + " (" + description + ")");
|
||||
@ -127,7 +119,7 @@ public class HelloPacketListener implements PluginMessageListener {
|
||||
}
|
||||
|
||||
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. " +
|
||||
"Axiom will try to use ViaVersion conversions, but this process may cause problems");
|
||||
@ -135,35 +127,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
|
||||
int maxBufferSize = plugin.configuration.getInt("max-block-buffer-packet-size");
|
||||
AxiomHandshakeEvent handshakeEvent = new AxiomHandshakeEvent(player, maxBufferSize);
|
||||
|
@ -33,10 +33,16 @@ import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.CapturedBlockState;
|
||||
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
import org.bukkit.craftbukkit.block.CraftBlockStates;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -44,6 +50,8 @@ import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@ -107,6 +115,8 @@ public class SetBlockPacketListener implements PluginMessageListener {
|
||||
player.connection.ackBlockChangesUpTo(sequenceId);
|
||||
}
|
||||
|
||||
BlockPlaceContext blockPlaceContext = new BlockPlaceContext(player, hand, player.getItemInHand(hand), blockHit);
|
||||
|
||||
if (!blockHit.getLocation().equals(Vec3.ZERO)) {
|
||||
org.bukkit.inventory.ItemStack heldItem;
|
||||
if (hand == InteractionHand.MAIN_HAND) {
|
||||
@ -126,12 +136,30 @@ public class SetBlockPacketListener implements PluginMessageListener {
|
||||
if (!playerInteractEvent.callEvent()) {
|
||||
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();
|
||||
|
||||
BlockPlaceContext blockPlaceContext = new BlockPlaceContext(player, hand, player.getItemInHand(hand), blockHit);
|
||||
|
||||
// Update blocks
|
||||
if (updateNeighbors) {
|
||||
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) {
|
||||
if (!this.plugin.canUseAxiom(serverPlayer.getBukkitEntity(), "axiom.blueprint.upload")) {
|
||||
friendlyByteBuf.writerIndex(friendlyByteBuf.readerIndex());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -18,12 +18,10 @@ blueprint-sharing: false
|
||||
allow-large-chunk-data-request: false
|
||||
|
||||
# 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
|
||||
# Using 'ignore' may result in corruption and is only provided for debugging purposes
|
||||
incompatible-data-version: "warn"
|
||||
unsupported-axiom-version: "warn"
|
||||
client-doesnt-support-restrictions: "ignore"
|
||||
|
||||
# Maximum packet size. Must not be less than 32767
|
||||
max-block-buffer-packet-size: 0x100000
|
||||
@ -59,11 +57,28 @@ blacklist-entities:
|
||||
# True allows players to see/manipulate marker entities
|
||||
send-markers: false
|
||||
|
||||
# True to enable Annotations on this server
|
||||
allow-annotations: false
|
||||
|
||||
# Disallowed blocks
|
||||
disallowed-blocks:
|
||||
# - "minecraft:wheat"
|
||||
# - "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
|
||||
packet-handlers:
|
||||
hello: true
|
||||
|
@ -32,6 +32,12 @@ permissions:
|
||||
axiom.blueprint.upload: true
|
||||
axiom.blueprint.request: 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.*:
|
||||
description: Allows use of all chunk-related features
|
||||
default: op
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren