3
0
Mirror von https://github.com/Moulberry/AxiomPaperPlugin.git synchronisiert 2024-09-29 16:00:04 +02:00

Add configuration options, major performance improvements

Dieser Commit ist enthalten in:
Moulberry 2023-10-14 11:59:05 +08:00
Ursprung d7523cba6a
Commit fa3f904f22
19 geänderte Dateien mit 355 neuen und 366 gelöschten Zeilen

Datei anzeigen

@ -19,7 +19,10 @@ import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.PacketFlow;
import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import org.bukkit.*;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -37,11 +40,23 @@ public class AxiomPaper extends JavaPlugin implements Listener {
public static AxiomPaper PLUGIN; // tsk tsk tsk
public final Set<UUID> activeAxiomPlayers = Collections.newSetFromMap(new ConcurrentHashMap<>());
public Configuration configuration;
@Override
public void onEnable() {
PLUGIN = this;
this.saveDefaultConfig();
configuration = this.getConfig();
Set<String> validResolutions = Set.of("kick", "warn", "ignore");
if (!validResolutions.contains(configuration.getString("incompatible-data-version"))) {
this.getLogger().warning("Invalid value for incompatible-data-version, expected 'kick', 'warn' or 'ignore'");
}
if (!validResolutions.contains(configuration.getString("unsupported-axiom-version"))) {
this.getLogger().warning("Invalid value for unsupported-axiom-version, expected 'kick', 'warn' or 'ignore'");
}
Bukkit.getPluginManager().registerEvents(this, this);
// Bukkit.getPluginManager().registerEvents(new WorldPropertiesExample(), this);
CompressedBlockEntity.initialize(this);
@ -56,40 +71,64 @@ public class AxiomPaper extends JavaPlugin implements Listener {
msg.registerOutgoingPluginChannel(this, "axiom:set_world_property");
msg.registerOutgoingPluginChannel(this, "axiom:ack_world_properties");
msg.registerIncomingPluginChannel(this, "axiom:hello", new HelloPacketListener(this, activeAxiomPlayers));
msg.registerIncomingPluginChannel(this, "axiom:set_gamemode", new SetGamemodePacketListener());
msg.registerIncomingPluginChannel(this, "axiom:set_fly_speed", new SetFlySpeedPacketListener());
msg.registerIncomingPluginChannel(this, "axiom:set_world_time", new SetTimePacketListener());
msg.registerIncomingPluginChannel(this, "axiom:set_world_property", new SetWorldPropertyListener());
msg.registerIncomingPluginChannel(this, "axiom:set_block", new SetBlockPacketListener(this));
msg.registerIncomingPluginChannel(this, "axiom:set_hotbar_slot", new SetHotbarSlotPacketListener());
msg.registerIncomingPluginChannel(this, "axiom:switch_active_hotbar", new SwitchActiveHotbarPacketListener());
msg.registerIncomingPluginChannel(this, "axiom:teleport", new TeleportPacketListener());
msg.registerIncomingPluginChannel(this, "axiom:set_editor_views", new SetEditorViewsPacketListener());
msg.registerIncomingPluginChannel(this, "axiom:request_chunk_data", new RequestChunkDataPacketListener(this));
if (configuration.getBoolean("packet-handlers.hello")) {
msg.registerIncomingPluginChannel(this, "axiom:hello", new HelloPacketListener(this, activeAxiomPlayers));
}
if (configuration.getBoolean("packet-handlers.set-gamemode")) {
msg.registerIncomingPluginChannel(this, "axiom:set_gamemode", new SetGamemodePacketListener(this));
}
if (configuration.getBoolean("packet-handlers.set-fly-speed")) {
msg.registerIncomingPluginChannel(this, "axiom:set_fly_speed", new SetFlySpeedPacketListener(this));
}
if (configuration.getBoolean("packet-handlers.set-world-time")) {
msg.registerIncomingPluginChannel(this, "axiom:set_world_time", new SetTimePacketListener(this));
}
if (configuration.getBoolean("packet-handlers.set-world-property")) {
msg.registerIncomingPluginChannel(this, "axiom:set_world_property", new SetWorldPropertyListener(this));
}
if (configuration.getBoolean("packet-handlers.set-single-block")) {
msg.registerIncomingPluginChannel(this, "axiom:set_block", new SetBlockPacketListener(this));
}
if (configuration.getBoolean("packet-handlers.set-hotbar-slot")) {
msg.registerIncomingPluginChannel(this, "axiom:set_hotbar_slot", new SetHotbarSlotPacketListener(this));
}
if (configuration.getBoolean("packet-handlers.switch-active-hotbar")) {
msg.registerIncomingPluginChannel(this, "axiom:switch_active_hotbar", new SwitchActiveHotbarPacketListener(this));
}
if (configuration.getBoolean("packet-handlers.teleport")) {
msg.registerIncomingPluginChannel(this, "axiom:teleport", new TeleportPacketListener(this));
}
if (configuration.getBoolean("packet-handlers.set-editor-views")) {
msg.registerIncomingPluginChannel(this, "axiom:set_editor_views", new SetEditorViewsPacketListener(this));
}
if (configuration.getBoolean("packet-handlers.request-chunk-data")) {
msg.registerIncomingPluginChannel(this, "axiom:request_chunk_data", new RequestChunkDataPacketListener(this));
}
SetBlockBufferPacketListener setBlockBufferPacketListener = new SetBlockBufferPacketListener(this);
if (configuration.getBoolean("packet-handlers.set-buffer")) {
SetBlockBufferPacketListener setBlockBufferPacketListener = new SetBlockBufferPacketListener(this);
ChannelInitializeListenerHolder.addListener(Key.key("axiom:handle_big_payload"), new ChannelInitializeListener() {
@Override
public void afterInitChannel(@NonNull Channel channel) {
var packets = ConnectionProtocol.PLAY.getPacketsByIds(PacketFlow.SERVERBOUND);
int payloadId = -1;
for (Map.Entry<Integer, Class<? extends Packet<?>>> entry : packets.entrySet()) {
if (entry.getValue() == ServerboundCustomPayloadPacket.class) {
payloadId = entry.getKey();
break;
ChannelInitializeListenerHolder.addListener(Key.key("axiom:handle_big_payload"), new ChannelInitializeListener() {
@Override
public void afterInitChannel(@NonNull Channel channel) {
var packets = ConnectionProtocol.PLAY.getPacketsByIds(PacketFlow.SERVERBOUND);
int payloadId = -1;
for (Map.Entry<Integer, Class<? extends Packet<?>>> entry : packets.entrySet()) {
if (entry.getValue() == ServerboundCustomPayloadPacket.class) {
payloadId = entry.getKey();
break;
}
}
if (payloadId < 0) {
throw new RuntimeException("Failed to find ServerboundCustomPayloadPacket id");
}
}
if (payloadId < 0) {
throw new RuntimeException("Failed to find ServerboundCustomPayloadPacket id");
}
Connection connection = (Connection) channel.pipeline().get("packet_handler");
channel.pipeline().addBefore("decoder", "axiom-big-payload-handler",
new AxiomBigPayloadHandler(payloadId, connection, setBlockBufferPacketListener));
}
});
Connection connection = (Connection) channel.pipeline().get("packet_handler");
channel.pipeline().addBefore("decoder", "axiom-big-payload-handler",
new AxiomBigPayloadHandler(payloadId, connection, setBlockBufferPacketListener));
}
});
}
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> {
HashSet<UUID> newActiveAxiomPlayers = new HashSet<>();
@ -111,6 +150,17 @@ public class AxiomPaper extends JavaPlugin implements Listener {
activeAxiomPlayers.clear();
activeAxiomPlayers.addAll(newActiveAxiomPlayers);
}, 20, 20);
int maxChunkRelightsPerTick = configuration.getInt("max-chunk-relights-per-tick");
int maxChunkSendsPerTick = configuration.getInt("max-chunk-sends-per-tick");
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> {
WorldExtension.tick(MinecraftServer.getServer(), maxChunkRelightsPerTick, maxChunkSendsPerTick);
}, 1, 1);
}
public boolean canUseAxiom(Player player) {
return player.hasPermission("axiom.*") && activeAxiomPlayers.contains(player.getUniqueId());
}
private final WeakHashMap<World, ServerWorldPropertiesRegistry> worldProperties = new WeakHashMap<>();

Datei anzeigen

@ -0,0 +1,105 @@
package com.moulberry.axiom;
import it.unimi.dsi.fastutil.longs.*;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.LevelChunk;
import java.util.*;
public class WorldExtension {
private static final Map<ResourceKey<Level>, WorldExtension> extensions = new HashMap<>();
public static WorldExtension get(ServerLevel serverLevel) {
WorldExtension extension = extensions.computeIfAbsent(serverLevel.dimension(), k -> new WorldExtension());
extension.level = serverLevel;
return extension;
}
public static void tick(MinecraftServer server, int maxChunkRelightsPerTick, int maxChunkSendsPerTick) {
extensions.keySet().retainAll(server.levelKeys());
for (ServerLevel level : server.getAllLevels()) {
WorldExtension extension = extensions.get(level.dimension());
if (extension != null) {
extension.level = level;
extension.tick(maxChunkRelightsPerTick, maxChunkSendsPerTick);
}
}
}
private ServerLevel level;
private final LongSet pendingChunksToSend = new LongOpenHashSet();
private final LongSet pendingChunksToLight = new LongOpenHashSet();
public void sendChunk(int cx, int cz) {
this.pendingChunksToSend.add(ChunkPos.asLong(cx, cz));
}
public void lightChunk(int cx, int cz) {
this.pendingChunksToLight.add(ChunkPos.asLong(cx, cz));
}
public void tick(int maxChunkRelightsPerTick, int maxChunkSendsPerTick) {
ChunkMap chunkMap = this.level.getChunkSource().chunkMap;
boolean sendAll = maxChunkSendsPerTick <= 0;
// Send chunks
LongIterator longIterator = this.pendingChunksToSend.longIterator();
while (longIterator.hasNext()) {
ChunkPos chunkPos = new ChunkPos(longIterator.nextLong());
List<ServerPlayer> players = chunkMap.getPlayers(chunkPos, false);
if (players.isEmpty()) continue;
LevelChunk chunk = this.level.getChunk(chunkPos.x, chunkPos.z);
var packet = new ClientboundLevelChunkWithLightPacket(chunk, this.level.getLightEngine(), null, null, false);
for (ServerPlayer player : players) {
player.connection.send(packet);
}
if (!sendAll) {
longIterator.remove();
maxChunkSendsPerTick -= 1;
if (maxChunkSendsPerTick <= 0) {
break;
}
}
}
if (sendAll) {
this.pendingChunksToSend.clear();
}
// Relight chunks
Set<ChunkPos> chunkSet = new HashSet<>();
longIterator = this.pendingChunksToLight.longIterator();
if (maxChunkRelightsPerTick <= 0) {
while (longIterator.hasNext()) {
chunkSet.add(new ChunkPos(longIterator.nextLong()));
}
this.pendingChunksToLight.clear();
} else {
while (longIterator.hasNext()) {
chunkSet.add(new ChunkPos(longIterator.nextLong()));
longIterator.remove();
maxChunkRelightsPerTick -= 1;
if (maxChunkRelightsPerTick <= 0) {
break;
}
}
}
this.level.getChunkSource().getLightEngine().relight(chunkSet, pos -> {}, count -> {});
}
}

Datei anzeigen

@ -12,10 +12,11 @@ public class AxiomHandshakeEvent extends Event implements Cancellable {
private final Player player;
private boolean cancelled = false;
private int maxBufferSize = 0x100000;
private int maxBufferSize;
public AxiomHandshakeEvent(Player player) {
public AxiomHandshakeEvent(Player player, int maxBufferSize) {
this.player = player;
this.maxBufferSize = maxBufferSize;
}
public Player getPlayer() {

Datei anzeigen

@ -1,39 +0,0 @@
package com.moulberry.axiom.integration;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
public class RegionProtection {
private final RegionProtectionWorldGuard worldGuard;
public RegionProtection(Player player, World world) {
if (Bukkit.getPluginManager().isPluginEnabled("WorldGuard")) {
this.worldGuard = RegionProtectionWorldGuard.tryCreate(player, world);
} else {
this.worldGuard = null;
}
}
public SectionProtection getSection(int cx, int cy, int cz) {
List<SectionProtection> protections = new ArrayList<>();
if (this.worldGuard != null) {
return this.worldGuard.getSection(cx, cy, cz);
}
// todo: PlotSquared
return SectionProtection.ALLOW;
}
public boolean canBuild(int x, int y, int z) {
if (this.worldGuard != null && !this.worldGuard.canBuild(x, y, z)) return false;
// todo: PlotSquared
return true;
}
}

Datei anzeigen

@ -1,183 +0,0 @@
package com.moulberry.axiom.integration;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.internal.platform.WorldGuardPlatform;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.FlagValueCalculator;
import com.sk89q.worldguard.protection.association.RegionAssociable;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.RegionGroup;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.*;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.google.common.base.Preconditions.checkNotNull;
public class RegionProtectionWorldGuard {
private final LocalPlayer player;
private final RegionManager regionManager;
public RegionProtectionWorldGuard(LocalPlayer player, RegionManager regionManager) {
this.player = player;
this.regionManager = regionManager;
}
@Nullable
public static RegionProtectionWorldGuard tryCreate(Player player, World world) {
WorldGuardPlatform platform = WorldGuard.getInstance().getPlatform();
RegionContainer regionContainer = platform.getRegionContainer();
if (regionContainer == null) return null;
com.sk89q.worldedit.world.World worldEditWorld = BukkitAdapter.adapt(world);
LocalPlayer worldGuardPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
// Don't do any protection if player has bypass
if (platform.getSessionManager().hasBypass(worldGuardPlayer, worldEditWorld)) {
// todo: enable bypass
return null;
}
RegionManager regionManager = regionContainer.get(worldEditWorld);
if (regionManager == null) return null;
return new RegionProtectionWorldGuard(worldGuardPlayer, regionManager);
}
public SectionProtection getSection(int cx, int cy, int cz) {
BlockVector3 min = BlockVector3.at(cx*16, cy*16, cz*16);
BlockVector3 max = BlockVector3.at(cx*16+15, cy*16+15, cz*16+15);
ProtectedRegion test = new ProtectedCuboidRegion("dummy", min, max);
ApplicableRegionSet regions = this.regionManager.getApplicableRegions(test, RegionQuery.QueryOption.COMPUTE_PARENTS);
int minimumPriority = Integer.MIN_VALUE;
Map<ProtectedRegion, StateFlag.State> consideredValues = new HashMap<>();
Set<ProtectedRegion> ignoredParents = new HashSet<>();
for (ProtectedRegion region : regions) {
int priority = FlagValueCalculator.getPriorityOf(region);
// todo: this logic doesn't work for us in determining ALLOW, DENY, CHECK
if (priority < minimumPriority) {
break;
}
// todo: have to keep track of 2 booleans: partialAllow & partialDeny
if (ignoredParents.contains(region)) {
continue;
}
StateFlag.State value = FlagValueCalculator.getEffectiveFlagOf(region, Flags.BUILD, this.player);
if (value != null) {
minimumPriority = priority;
consideredValues.put(region, value);
}
addParents(ignoredParents, region);
// The BUILD flag is implicitly set on every region where
// PASSTHROUGH is not set to ALLOW
if (minimumPriority != priority && Flags.BUILD.implicitlySetWithMembership() &&
FlagValueCalculator.getEffectiveFlagOf(region, Flags.PASSTHROUGH, this.player) != StateFlag.State.ALLOW) {
minimumPriority = priority;
}
}
if (consideredValues.isEmpty()) {
if (Flags.BUILD.usesMembershipAsDefault()) {
// todo
// switch (getMembership(subject)) {
// case FAIL:
// return ImmutableList.of();
// case SUCCESS:
// return (Collection<V>) ImmutableList.of(StateFlag.State.ALLOW);
// }
}
// System.out.println("returning default");
StateFlag.State fallback = Flags.BUILD.getDefault();
return fallback == StateFlag.State.DENY ? SectionProtection.DENY : SectionProtection.ALLOW;
}
boolean hasPartialDeny = false;
for (Map.Entry<ProtectedRegion, StateFlag.State> entry : consideredValues.entrySet()) {
ProtectedRegion region = entry.getKey();
if (entry.getValue() == StateFlag.State.DENY) {
// System.out.println("found region with deny!");
if (region instanceof GlobalProtectedRegion) {
return SectionProtection.DENY;
} else if (region instanceof ProtectedCuboidRegion && doesRegionCompletelyContainSection(region, cx, cy, cz)) {
return SectionProtection.DENY;
}
hasPartialDeny = true;
}
}
if (hasPartialDeny) {
// System.out.println("returning check!");
return new SectionProtection() {
@Override
public SectionState getSectionState() {
return SectionState.CHECK;
}
@Override
public boolean check(int wx, int wy, int wz) {
return true;
}
};
// return complex thing
}
// System.out.println("returning allow!");
return SectionProtection.ALLOW;
}
private boolean doesRegionCompletelyContainSection(ProtectedRegion region, int cx, int cy, int cz) {
BlockVector3 regionMin = region.getMinimumPoint();
if (regionMin.getBlockX() > cx*16) return false;
if (regionMin.getBlockY() > cy*16) return false;
if (regionMin.getBlockZ() > cz*16) return false;
BlockVector3 regionMax = region.getMaximumPoint();
if (regionMax.getBlockX() < cx*16+15) return false;
if (regionMax.getBlockY() < cy*16+15) return false;
if (regionMax.getBlockZ() < cz*16+15) return false;
return true;
}
private void addParents(Set<ProtectedRegion> ignored, ProtectedRegion region) {
ProtectedRegion parent = region.getParent();
while (parent != null) {
ignored.add(parent);
parent = parent.getParent();
}
}
public boolean canBuild(int x, int y, int z) {
return this.regionManager.getApplicableRegions(BlockVector3.at(x, y, z)).testState(this.player, Flags.BUILD);
}
public boolean isAllowed(LocalPlayer player, ProtectedRegion protectedRegion) {
return protectedRegion.isOwner(player) || protectedRegion.isMember(player);
}
}

Datei anzeigen

@ -1,38 +0,0 @@
package com.moulberry.axiom.integration;
public interface SectionProtection {
SectionProtection ALLOW = new SectionProtection() {
@Override
public SectionState getSectionState() {
return SectionState.ALLOW;
}
@Override
public boolean check(int wx, int wy, int wz) {
return true;
}
};
SectionProtection DENY = new SectionProtection() {
@Override
public SectionState getSectionState() {
return SectionState.DENY;
}
@Override
public boolean check(int wx, int wy, int wz) {
return false;
}
};
enum SectionState {
ALLOW,
DENY,
CHECK
}
SectionState getSectionState();
boolean check(int wx, int wy, int wz);
}

Datei anzeigen

@ -9,6 +9,7 @@ import com.moulberry.axiom.persistence.UUIDDataType;
import com.moulberry.axiom.world_properties.server.ServerWorldPropertiesRegistry;
import io.netty.buffer.Unpooled;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.SharedConstants;
import net.minecraft.network.FriendlyByteBuf;
import org.bukkit.Bukkit;
@ -48,19 +49,38 @@ public class HelloPacketListener implements PluginMessageListener {
int serverDataVersion = SharedConstants.getCurrentVersion().getDataVersion().getVersion();
if (dataVersion != serverDataVersion) {
player.kick(Component.text("Axiom: Incompatible data version detected (client " + dataVersion +
", server " + serverDataVersion + "), are you using ViaVersion?"));
return;
Component text = Component.text("Axiom: Incompatible data version detected (client " + dataVersion +
", server " + serverDataVersion + "), are you using ViaVersion?");
String incompatibleDataVersion = plugin.configuration.getString("incompatible-data-version");
if (incompatibleDataVersion == null) incompatibleDataVersion = "kick";
if (incompatibleDataVersion.equals("warn")) {
player.sendMessage(text.color(NamedTextColor.RED));
return;
} else if (!incompatibleDataVersion.equals("ignore")) {
player.kick(text);
return;
}
}
if (apiVersion != AxiomConstants.API_VERSION) {
player.kick(Component.text("Unsupported Axiom API Version. Server supports " + AxiomConstants.API_VERSION +
", while client is " + apiVersion));
return;
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;
}
}
// Call handshake event
AxiomHandshakeEvent handshakeEvent = new AxiomHandshakeEvent(player);
int maxBufferSize = plugin.configuration.getInt("max-block-buffer-packet-size");
AxiomHandshakeEvent handshakeEvent = new AxiomHandshakeEvent(player, maxBufferSize);
Bukkit.getPluginManager().callEvent(handshakeEvent);
if (handshakeEvent.isCancelled()) {
return;

Datei anzeigen

@ -3,6 +3,7 @@ package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomConstants;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.buffer.CompressedBlockEntity;
import com.moulberry.axiom.event.AxiomModifyWorldEvent;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.longs.*;
import net.minecraft.core.BlockPos;
@ -21,6 +22,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.PalettedContainer;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener;
@ -33,7 +35,6 @@ public class RequestChunkDataPacketListener implements PluginMessageListener {
private static final ResourceLocation RESPONSE_ID = new ResourceLocation("axiom:response_chunk_data");
private final AxiomPaper plugin;
public RequestChunkDataPacketListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@ -44,12 +45,20 @@ public class RequestChunkDataPacketListener implements PluginMessageListener {
FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message));
long id = friendlyByteBuf.readLong();
if (!bukkitPlayer.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(bukkitPlayer)) {
// We always send an 'empty' response in order to make the client happy
sendEmptyResponse(player, id);
return;
}
// Call AxiomModifyWorldEvent event
AxiomModifyWorldEvent modifyWorldEvent = new AxiomModifyWorldEvent(bukkitPlayer, bukkitPlayer.getWorld());
Bukkit.getPluginManager().callEvent(modifyWorldEvent);
if (modifyWorldEvent.isCancelled()) {
sendEmptyResponse(player, id);
return;
}
MinecraftServer server = player.getServer();
if (server == null) {
sendEmptyResponse(player, id);

Datei anzeigen

@ -1,27 +1,11 @@
package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.WorldExtension;
import com.moulberry.axiom.buffer.BiomeBuffer;
import com.moulberry.axiom.buffer.BlockBuffer;
import com.moulberry.axiom.buffer.CompressedBlockEntity;
import com.moulberry.axiom.event.AxiomModifyWorldEvent;
import com.moulberry.axiom.integration.RegionProtection;
import com.moulberry.axiom.integration.SectionProtection;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
import net.minecraft.core.BlockPos;
@ -41,7 +25,6 @@ import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
@ -96,7 +79,7 @@ public class SetBlockBufferPacketListener {
applyBlockBuffer(player, server, buffer, worldKey);
} else if (type == 1) {
BiomeBuffer buffer = BiomeBuffer.load(friendlyByteBuf);
applyBiomeBuffer(server, buffer, worldKey);
applyBiomeBuffer(player, server, buffer, worldKey);
} else {
throw new RuntimeException("Unknown buffer type: " + type);
}
@ -109,17 +92,18 @@ public class SetBlockBufferPacketListener {
ServerLevel world = server.getLevel(worldKey);
if (world == null) return;
if (!this.plugin.canUseAxiom(player.getBukkitEntity())) {
return;
}
// Call AxiomModifyWorldEvent event
AxiomModifyWorldEvent modifyWorldEvent = new AxiomModifyWorldEvent(player.getBukkitEntity(), world.getWorld());
Bukkit.getPluginManager().callEvent(modifyWorldEvent);
if (modifyWorldEvent.isCancelled()) return;
// RegionProtection regionProtection = new RegionProtection(player.getBukkitEntity(), world.getWorld());
// Allowed, apply buffer
BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos();
var lightEngine = world.getChunkSource().getLightEngine();
WorldExtension extension = WorldExtension.get(world);
BlockState emptyState = BlockBuffer.EMPTY_STATE;
@ -133,17 +117,7 @@ public class SetBlockBufferPacketListener {
continue;
}
// SectionProtection sectionProtection = regionProtection.getSection(cx, cy, cz);
// switch (sectionProtection.getSectionState()) {
// case ALLOW -> sectionProtection = null;
// case DENY -> {
// continue;
// }
// case CHECK -> {}
// }
LevelChunk chunk = world.getChunk(cx, cz);
chunk.setUnsaved(true);
LevelChunkSection section = chunk.getSection(world.getSectionIndexFromSectionY(cy));
PalettedContainer<BlockState> sectionStates = section.getStates();
@ -163,6 +137,12 @@ public class SetBlockBufferPacketListener {
}
}
boolean sectionChanged = false;
boolean sectionLightChanged = false;
boolean containerMaybeHasPoi = container.maybeHas(PoiTypes::hasPoi);
boolean sectionMaybeHasPoi = section.maybeHas(PoiTypes::hasPoi);
Short2ObjectMap<CompressedBlockEntity> blockEntityChunkMap = buffer.getBlockEntityChunkMap(entry.getLongKey());
for (int x = 0; x < 16; x++) {
@ -171,28 +151,19 @@ public class SetBlockBufferPacketListener {
BlockState blockState = container.get(x, y, z);
if (blockState == emptyState) continue;
// switch (sectionProtection.getSectionState()) {
// case ALLOW -> {}
// case DENY -> blockState = Blocks.REDSTONE_BLOCK.defaultBlockState();
// case CHECK -> blockState = Blocks.DIAMOND_BLOCK.defaultBlockState();
// }
int bx = cx*16 + x;
int by = cy*16 + y;
int bz = cz*16 + z;
// if (!regionProtection.canBuild(bx, by, bz)) {
// continue;
// }
blockPos.set(bx, by, bz);
if (hasOnlyAir && blockState.isAir()) {
continue;
}
BlockState old = section.setBlockState(x, y, z, blockState, true);
if (blockState != old) {
sectionChanged = true;
blockPos.set(bx, by, bz);
Block block = blockState.getBlock();
motionBlocking.update(x, by, z, blockState);
motionBlockingNoLeaves.update(x, by, z, blockState);
@ -245,18 +216,12 @@ public class SetBlockBufferPacketListener {
chunk.removeBlockEntity(blockPos);
}
// Mark block changed
world.getChunkSource().blockChanged(blockPos); // todo: maybe simply resend chunk instead of this?
// Update Light
if (LightEngine.hasDifferentLightProperties(chunk, blockPos, old, blockState)) {
chunk.getSkyLightSources().update(chunk, x, by, z);
lightEngine.checkBlock(blockPos);
}
sectionLightChanged |= LightEngine.hasDifferentLightProperties(chunk, blockPos, old, blockState);
// Update Poi
Optional<Holder<PoiType>> newPoi = PoiTypes.forState(blockState);
Optional<Holder<PoiType>> oldPoi = PoiTypes.forState(old);
Optional<Holder<PoiType>> newPoi = containerMaybeHasPoi ? PoiTypes.forState(blockState) : Optional.empty();
Optional<Holder<PoiType>> oldPoi = sectionMaybeHasPoi ? PoiTypes.forState(old) : Optional.empty();
if (!Objects.equals(oldPoi, newPoi)) {
if (oldPoi.isPresent()) world.getPoiManager().remove(blockPos);
if (newPoi.isPresent()) world.getPoiManager().add(blockPos, newPoi.get());
@ -270,16 +235,33 @@ public class SetBlockBufferPacketListener {
if (hasOnlyAir != nowHasOnlyAir) {
world.getChunkSource().getLightEngine().updateSectionStatus(SectionPos.of(cx, cy, cz), nowHasOnlyAir);
}
if (sectionChanged) {
extension.sendChunk(cx, cz);
chunk.setUnsaved(true);
}
if (sectionLightChanged) {
extension.lightChunk(cx, cz);
}
}
});
}
private void applyBiomeBuffer(MinecraftServer server, BiomeBuffer biomeBuffer, ResourceKey<Level> worldKey) {
private void applyBiomeBuffer(ServerPlayer player, MinecraftServer server, BiomeBuffer biomeBuffer, ResourceKey<Level> worldKey) {
server.execute(() -> {
ServerLevel world = server.getLevel(worldKey);
if (world == null) return;
if (!this.plugin.canUseAxiom(player.getBukkitEntity())) {
return;
}
// Call AxiomModifyWorldEvent event
AxiomModifyWorldEvent modifyWorldEvent = new AxiomModifyWorldEvent(player.getBukkitEntity(), world.getWorld());
Bukkit.getPluginManager().callEvent(modifyWorldEvent);
if (modifyWorldEvent.isCancelled()) return;
Set<LevelChunk> changedChunks = new HashSet<>();
int minSection = world.getMinSection();

Datei anzeigen

@ -62,7 +62,7 @@ public class SetBlockPacketListener implements PluginMessageListener {
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player bukkitPlayer, @NotNull byte[] message) {
if (!bukkitPlayer.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(bukkitPlayer)) {
return;
}

Datei anzeigen

@ -1,6 +1,7 @@
package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomConstants;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.View;
import com.moulberry.axiom.persistence.UUIDDataType;
import io.netty.buffer.Unpooled;
@ -16,9 +17,14 @@ import java.util.UUID;
public class SetEditorViewsPacketListener implements PluginMessageListener {
private final AxiomPaper plugin;
public SetEditorViewsPacketListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
if (!player.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(player)) {
return;
}

Datei anzeigen

@ -1,5 +1,6 @@
package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.event.AxiomFlySpeedChangeEvent;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
@ -11,9 +12,14 @@ import org.jetbrains.annotations.NotNull;
public class SetFlySpeedPacketListener implements PluginMessageListener {
private final AxiomPaper plugin;
public SetFlySpeedPacketListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
if (!player.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(player)) {
return;
}

Datei anzeigen

@ -1,5 +1,6 @@
package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.event.AxiomGameModeChangeEvent;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
@ -13,9 +14,14 @@ import org.jetbrains.annotations.NotNull;
public class SetGamemodePacketListener implements PluginMessageListener {
private final AxiomPaper plugin;
public SetGamemodePacketListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
if (!player.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(player)) {
return;
}

Datei anzeigen

@ -1,6 +1,7 @@
package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomConstants;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.persistence.ItemStackDataType;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
@ -15,9 +16,14 @@ import org.jetbrains.annotations.NotNull;
public class SetHotbarSlotPacketListener implements PluginMessageListener {
private final AxiomPaper plugin;
public SetHotbarSlotPacketListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
if (!player.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(player)) {
return;
}

Datei anzeigen

@ -1,5 +1,7 @@
package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.event.AxiomModifyWorldEvent;
import com.moulberry.axiom.event.AxiomTimeChangeEvent;
import io.netty.buffer.Unpooled;
import net.minecraft.core.registries.Registries;
@ -16,9 +18,14 @@ import org.jetbrains.annotations.NotNull;
public class SetTimePacketListener implements PluginMessageListener {
private final AxiomPaper plugin;
public SetTimePacketListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
if (!player.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(player)) {
return;
}
@ -32,7 +39,12 @@ public class SetTimePacketListener implements PluginMessageListener {
ServerLevel level = ((CraftWorld)player.getWorld()).getHandle();
if (!level.dimension().equals(key)) return;
// Call event
// Call modify world
AxiomModifyWorldEvent modifyWorldEvent = new AxiomModifyWorldEvent(player, player.getWorld());
Bukkit.getPluginManager().callEvent(modifyWorldEvent);
if (modifyWorldEvent.isCancelled()) return;
// Call time change event
AxiomTimeChangeEvent timeChangeEvent = new AxiomTimeChangeEvent(player, time, freezeTime);
Bukkit.getPluginManager().callEvent(timeChangeEvent);
if (timeChangeEvent.isCancelled()) return;

Datei anzeigen

@ -12,9 +12,14 @@ import org.jetbrains.annotations.NotNull;
public class SetWorldPropertyListener implements PluginMessageListener {
private final AxiomPaper plugin;
public SetWorldPropertyListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
if (!player.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(player)) {
return;
}

Datei anzeigen

@ -1,6 +1,7 @@
package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomConstants;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.persistence.ItemStackDataType;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
@ -17,9 +18,14 @@ import org.jetbrains.annotations.NotNull;
public class SwitchActiveHotbarPacketListener implements PluginMessageListener {
private final AxiomPaper plugin;
public SwitchActiveHotbarPacketListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
if (!player.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(player)) {
return;
}

Datei anzeigen

@ -1,5 +1,6 @@
package com.moulberry.axiom.packet;
import com.moulberry.axiom.AxiomPaper;
import com.moulberry.axiom.event.AxiomGameModeChangeEvent;
import com.moulberry.axiom.event.AxiomTeleportEvent;
import io.netty.buffer.Unpooled;
@ -14,9 +15,14 @@ import org.jetbrains.annotations.NotNull;
public class TeleportPacketListener implements PluginMessageListener {
private final AxiomPaper plugin;
public TeleportPacketListener(AxiomPaper plugin) {
this.plugin = plugin;
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message) {
if (!player.hasPermission("axiom.*")) {
if (!this.plugin.canUseAxiom(player)) {
return;
}

Datei anzeigen

@ -0,0 +1,29 @@
# Max chunk sends per tick (per-world), 0 = no limit
max-chunk-sends-per-tick: 0
# Max chunk relights per tick (per-world), 0 = no limit
max-chunk-relights-per-tick: 0
# Action to take when a user with an incompatible Minecraft version or Axiom version joins
# Valid actions are 'kick', 'warn' and 'ignore'
# Using 'ignore' may result in corruption and is only provided for debugging purposes
incompatible-data-version: "kick"
unsupported-axiom-version: "kick"
# Maximum packet size. Must not be less than 32767
max-block-buffer-packet-size: 0x100000
# Toggles for individual packet handlers. May break certain features
packet-handlers:
hello: true
set-gamemode: true
set-fly-speed: true
set-world-time: true
set-world-property: true
set-single-block: true
set-hotbar-slot: true
switch-active-hotbar: true
teleport: true
set-editor-views: true
request-chunk-data: true
set-buffer: true