mirror of
https://github.com/LeavesMC/Leaves.git
synced 2025-12-19 14:59:32 +00:00
759 lines
36 KiB
Diff
759 lines
36 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
|
Date: Mon, 28 Nov 2022 15:34:15 +0800
|
|
Subject: [PATCH] PCA sync protocol
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
index f7870d551bf6045b649c9c8768b5ad5c8d3488ae..ca4ff892bf647f9ee7c05e6afb1d88c5c8b46eaf 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -241,6 +241,7 @@ import org.bukkit.inventory.CraftingInventory;
|
|
import org.bukkit.inventory.EquipmentSlot;
|
|
import org.bukkit.inventory.InventoryView;
|
|
import org.bukkit.inventory.SmithingInventory;
|
|
+import top.leavesmc.leaves.util.ProtocolUtils;
|
|
// CraftBukkit end
|
|
|
|
public class ServerGamePacketListenerImpl implements ServerPlayerConnection, TickablePacketListener, ServerGamePacketListener {
|
|
@@ -3547,6 +3548,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
this.disconnect("Invalid payload UNREGISTER!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD); // Paper - kick event cause
|
|
}
|
|
} else {
|
|
+ // Leaves start - leaves extra protocol
|
|
+ try {
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol && ProtocolUtils.isNamespacePacket(packet, top.leavesmc.leaves.protocol.PcaSyncProtocol.PROTOCOL_ID)) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.handlePacket(server, player, packet);
|
|
+ }
|
|
+ } catch (Exception ex) {
|
|
+ ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex);
|
|
+ this.disconnect("Invalid custom payload!", org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PAYLOAD);
|
|
+ }
|
|
+ // Leaves end - leaves extra protocol
|
|
try {
|
|
byte[] data = new byte[packet.data.readableBytes()];
|
|
packet.data.readBytes(data);
|
|
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
index 3c1ea8850c5d482d77c0bc137d72fc59dc337979..0f5c3159ed9d15024b35d32d282994f67568b2eb 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -396,6 +396,7 @@ public abstract class PlayerList {
|
|
bot1.render(playerconnection, true,player.getBukkitEntity().getWorld() == bot1.getBukkitEntity().getWorld())); // Leaves - render bot
|
|
}
|
|
// Leaves end - bot support
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.onJoin(player); // Leaves - pca
|
|
|
|
final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
|
index 72d660cd2ade39335024897cffb8b8a151a7cb71..228abbb9ecca77694ccec405342e67c19195163b 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
|
@@ -346,6 +346,11 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
|
|
|
|
@Override
|
|
public void containerChanged(Container sender) {
|
|
+ // Leaves start - pca
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncEntityToClient(this);
|
|
+ }
|
|
+ // Leaves end - pca
|
|
boolean flag = this.isSaddled();
|
|
|
|
this.updateContainerEquipment();
|
|
diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
|
|
index ca96b893e22de3ae7c11d5cded51edf70bdcb6f2..a0380713ff1e3faa285c76ea45f75c9c480caafe 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java
|
|
@@ -65,6 +65,15 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa
|
|
super(type, world);
|
|
this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, 16.0F);
|
|
this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, -1.0F);
|
|
+ // Leaves start - pca
|
|
+ if (!this.level.isClientSide()) {
|
|
+ this.inventory.addListener(inventory -> {
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncEntityToClient(this);
|
|
+ }
|
|
+ });
|
|
+ }
|
|
+ // Leaves end - pca
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
|
index b8fb7b5a347298ada16bc8b818edf1863e3f6040..ca71b5b61d85df4a3e74c69823184b52cab98f67 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java
|
|
@@ -129,7 +129,13 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme
|
|
}
|
|
|
|
@Override
|
|
- public void setChanged() {}
|
|
+ public void setChanged() {
|
|
+ // Leaves start - pca
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncEntityToClient(this);
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+ }
|
|
|
|
@Override
|
|
public boolean stillValid(Player player) {
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
|
index cac2768fe520b591990c7bc943ae7e95f49efb31..59938c323ad2597af03a310e930d1a61f1a456c7 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
|
@@ -568,6 +568,16 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
|
|
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ @Override
|
|
+ public void setChanged() {
|
|
+ super.setChanged();
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
@Override
|
|
public boolean stillValid(net.minecraft.world.entity.player.Player player) {
|
|
return this.level.getBlockEntity(this.worldPosition) != this ? false : player.distanceToSqr((double) this.worldPosition.getX() + 0.5D, (double) this.worldPosition.getY() + 0.5D, (double) this.worldPosition.getZ() + 0.5D) <= 64.0D;
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
|
index 416aa989ebb18a8741cc9d605a1180ab830f6643..213bc3c11ff4ed9bc761e8153aa669d1e2301960 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java
|
|
@@ -131,6 +131,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity {
|
|
this.items = list;
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ @Override
|
|
+ public void setChanged() {
|
|
+ super.setChanged();
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
@Override
|
|
protected Component getDefaultName() {
|
|
return Component.translatable("container.barrel");
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
|
index 41c9f074203915c31c1ae7a160ce509c13383f84..4c9e84dcd154a4306659ef41ab40127ea8452835 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
|
@@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
|
|
import java.util.Arrays;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
+import java.util.Objects;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
@@ -127,6 +128,11 @@ public class BeehiveBlockEntity extends BlockEntity {
|
|
super.setChanged();
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ // Leaves end - pca
|
|
return list;
|
|
}
|
|
|
|
@@ -188,6 +194,12 @@ public class BeehiveBlockEntity extends BlockEntity {
|
|
this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, this.getBlockState()));
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
entity.discard();
|
|
super.setChanged();
|
|
}
|
|
@@ -334,6 +346,11 @@ public class BeehiveBlockEntity extends BlockEntity {
|
|
if (BeehiveBlockEntity.releaseOccupant(world, pos, state, tileentitybeehive_hivebee, (List) null, tileentitybeehive_releasestatus, flowerPos)) {
|
|
flag = true;
|
|
iterator.remove();
|
|
+ // Leaves start - pca
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(Objects.requireNonNull(world.getBlockEntity(pos)));
|
|
+ }
|
|
+ // Leaves end - pca
|
|
// CraftBukkit start
|
|
} else {
|
|
tileentitybeehive_hivebee.exitTickCounter = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable // Paper - use exitTickCounter to keep actual bee life
|
|
@@ -385,6 +402,11 @@ public class BeehiveBlockEntity extends BlockEntity {
|
|
this.maxBees = nbt.getInt("Bukkit.MaxEntities");
|
|
}
|
|
// CraftBukkit end
|
|
+ // Leaves start - pca
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ // Leaves end - pca
|
|
}
|
|
|
|
@Override
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
|
index 55006724ccec9f3de828ec18693728e9741ff65f..4391127a685fa16ce76e35f7c17b2d7056b13ea1 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
|
@@ -328,6 +328,16 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
|
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ @Override
|
|
+ public void setChanged() {
|
|
+ super.setChanged();
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
@Override
|
|
public boolean stillValid(Player player) {
|
|
return this.level.getBlockEntity(this.worldPosition) != this ? false : player.distanceToSqr((double) this.worldPosition.getX() + 0.5D, (double) this.worldPosition.getY() + 0.5D, (double) this.worldPosition.getZ() + 0.5D) <= 64.0D;
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
|
index a71414397bd45ee7bcacfeef0041d80dfa25f114..1d6c7a04b8246a60d80325e1615e50573b17a6bb 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
|
@@ -190,6 +190,16 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
|
this.items = list;
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ @Override
|
|
+ public void setChanged() {
|
|
+ super.setChanged();
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
@Override
|
|
public float getOpenNess(float tickDelta) {
|
|
return this.chestLidController.getOpenness(tickDelta);
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ComparatorBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ComparatorBlockEntity.java
|
|
index 9b2c162c362fcf6093a3bf6da715ae8f18176c82..84b877a712a883b868b139d29da7e09c9552a1e5 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/ComparatorBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/ComparatorBlockEntity.java
|
|
@@ -23,6 +23,16 @@ public class ComparatorBlockEntity extends BlockEntity {
|
|
this.output = nbt.getInt("OutputSignal");
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ @Override
|
|
+ public void setChanged() {
|
|
+ super.setChanged();
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
public int getOutputSignal() {
|
|
return this.output;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
|
index 881379681c39230a00b3a1f11cd87498984396c7..e01eb2025458cf311348c58a1530854053af78f4 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
|
@@ -92,6 +92,16 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity {
|
|
return -1;
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ @Override
|
|
+ public void setChanged() {
|
|
+ super.setChanged();
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
@Override
|
|
protected Component getDefaultName() {
|
|
return Component.translatable("container.dispenser");
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
index ccad692aba2ed77259f6814d88f01b91ed9d229b..01bf32fd730000bdf3a71abe0ad9546ce3775ee7 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
|
@@ -125,6 +125,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ @Override
|
|
+ public void setChanged() {
|
|
+ super.setChanged();
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
@Override
|
|
protected Component getDefaultName() {
|
|
return Component.translatable("container.hopper");
|
|
@@ -165,6 +175,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
|
if (flag) {
|
|
blockEntity.setCooldown(world.spigotConfig.hopperTransfer); // Spigot
|
|
setChanged(world, pos, state);
|
|
+ // Leaves start - pca
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(blockEntity);
|
|
+ }
|
|
+ // Leaves end - pca
|
|
return true;
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
|
index b7686fd63b7c5d88c3a12ec4ee9bc01a17f997e0..25a9c38c60d183bb65b14f4d7550ab98b431c218 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
|
@@ -259,6 +259,16 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl
|
|
this.itemStacks = list;
|
|
}
|
|
|
|
+ // Leaves start - pca
|
|
+ @Override
|
|
+ public void setChanged() {
|
|
+ super.setChanged();
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(this);
|
|
+ }
|
|
+ }
|
|
+ // Leaves end - pca
|
|
+
|
|
@Override
|
|
public int[] getSlotsForFace(Direction side) {
|
|
return ShulkerBoxBlockEntity.SLOTS;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
index 4d22a40e7ff0b88aa204e0da81e71757ecc1dd7f..d52f9d6685a17f46186ed706d59cbe3819234a0d 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -385,6 +385,7 @@ public final class CraftServer implements Server {
|
|
MapPalette.setMapColorCache(new CraftMapColorCache(this.logger));
|
|
}
|
|
datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.init(); // Leaves - pca
|
|
}
|
|
|
|
public boolean getCommandBlockOverride(String command) {
|
|
@@ -980,6 +981,13 @@ public final class CraftServer implements Server {
|
|
org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot
|
|
this.console.paperConfigurations.reloadConfigs(this.console);
|
|
top.leavesmc.leaves.LeavesConfig.init((File) console.options.valueOf("leaves-settings")); // Leaves - Server Config
|
|
+ // Leaves start - pca
|
|
+ if (top.leavesmc.leaves.LeavesConfig.pcaSyncProtocol) {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.enablePcaSyncProtocolGlobal();
|
|
+ } else {
|
|
+ top.leavesmc.leaves.protocol.PcaSyncProtocol.disablePcaSyncProtocolGlobal();
|
|
+ }
|
|
+ // Leaves end - pca
|
|
for (ServerLevel world : this.console.getAllLevels()) {
|
|
// world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty
|
|
world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters, config.spawnAnimals); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean))
|
|
diff --git a/src/main/java/top/leavesmc/leaves/LeavesConfig.java b/src/main/java/top/leavesmc/leaves/LeavesConfig.java
|
|
index d4a65880aed6f7bc2973e8e6011f3959f37caf15..cb09cbb64bfe8de91a78b2dd1dc135f5d5688477 100644
|
|
--- a/src/main/java/top/leavesmc/leaves/LeavesConfig.java
|
|
+++ b/src/main/java/top/leavesmc/leaves/LeavesConfig.java
|
|
@@ -384,6 +384,21 @@ public final class LeavesConfig {
|
|
simplerVanillaShapelessRecipes = getBoolean("settings.performance.simpler-vanilla-shapeless-recipes", simplerVanillaShapelessRecipes);
|
|
}
|
|
|
|
+ public static boolean pcaSyncProtocol = false;
|
|
+ private static void pcaSyncProtocol() {
|
|
+ pcaSyncProtocol = getBoolean("settings.protocol.pca-sync-protocol", pcaSyncProtocol);
|
|
+ }
|
|
+
|
|
+ public static String pcaSyncPlayerEntity = "OPS";
|
|
+ private static final List<String> pcaSyncPlayerEntityList = List.of("NOBODY", "BOT", "OPS", "OPS_AND_SELF", "EVERYONE");
|
|
+ private static void pcaSyncPlayerEntity() {
|
|
+ pcaSyncPlayerEntity = getString("settings.protocol.pca-sync-player-entity", pcaSyncPlayerEntity);
|
|
+ if (!pcaSyncPlayerEntityList.contains(pcaSyncPlayerEntity)) {
|
|
+ pcaSyncPlayerEntity = "OPS";
|
|
+ LeavesLogger.LOGGER.severe("pca-sync-player-entity value error, reset to OPS");
|
|
+ }
|
|
+ }
|
|
+
|
|
public static final class WorldConfig {
|
|
|
|
public final String worldName;
|
|
diff --git a/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java b/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..d8f84c38aaae14a093bfe8e901a3be802617fb12
|
|
--- /dev/null
|
|
+++ b/src/main/java/top/leavesmc/leaves/protocol/PcaSyncProtocol.java
|
|
@@ -0,0 +1,357 @@
|
|
+package top.leavesmc.leaves.protocol;
|
|
+
|
|
+import io.netty.buffer.Unpooled;
|
|
+import net.minecraft.core.BlockPos;
|
|
+import net.minecraft.nbt.CompoundTag;
|
|
+import net.minecraft.network.FriendlyByteBuf;
|
|
+import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
|
+import net.minecraft.resources.ResourceLocation;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.level.ServerLevel;
|
|
+import net.minecraft.server.level.ServerPlayer;
|
|
+import net.minecraft.world.entity.Entity;
|
|
+import net.minecraft.world.entity.player.Player;
|
|
+import net.minecraft.world.level.Level;
|
|
+import net.minecraft.world.level.block.ChestBlock;
|
|
+import net.minecraft.world.level.block.entity.BlockEntity;
|
|
+import net.minecraft.world.level.block.state.BlockState;
|
|
+import net.minecraft.world.level.block.state.properties.ChestType;
|
|
+import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
+import org.apache.commons.lang3.tuple.MutablePair;
|
|
+import org.apache.commons.lang3.tuple.Pair;
|
|
+import org.apache.logging.log4j.util.TriConsumer;
|
|
+import org.jetbrains.annotations.Contract;
|
|
+import org.jetbrains.annotations.NotNull;
|
|
+import org.jetbrains.annotations.Nullable;
|
|
+import top.leavesmc.leaves.LeavesConfig;
|
|
+import top.leavesmc.leaves.LeavesLogger;
|
|
+import top.leavesmc.leaves.bot.ServerBot;
|
|
+import top.leavesmc.leaves.util.ProtocolUtils;
|
|
+
|
|
+import java.util.HashMap;
|
|
+import java.util.HashSet;
|
|
+import java.util.Map;
|
|
+import java.util.Set;
|
|
+import java.util.concurrent.locks.ReentrantLock;
|
|
+
|
|
+public class PcaSyncProtocol {
|
|
+
|
|
+ public static final String PROTOCOL_ID = "pca";
|
|
+
|
|
+ public static final ReentrantLock lock = new ReentrantLock(true);
|
|
+ public static final ReentrantLock pairLock = new ReentrantLock(true);
|
|
+
|
|
+ // send
|
|
+ private static final ResourceLocation ENABLE_PCA_SYNC_PROTOCOL = id("enable_pca_sync_protocol");
|
|
+ private static final ResourceLocation DISABLE_PCA_SYNC_PROTOCOL = id("disable_pca_sync_protocol");
|
|
+ private static final ResourceLocation UPDATE_ENTITY = id("update_entity");
|
|
+ private static final ResourceLocation UPDATE_BLOCK_ENTITY = id("update_block_entity");
|
|
+ // call
|
|
+ private static final ResourceLocation SYNC_BLOCK_ENTITY = id("sync_block_entity");
|
|
+ private static final ResourceLocation SYNC_ENTITY = id("sync_entity");
|
|
+ private static final ResourceLocation CANCEL_SYNC_BLOCK_ENTITY = id("cancel_sync_block_entity");
|
|
+ private static final ResourceLocation CANCEL_SYNC_ENTITY = id("cancel_sync_entity");
|
|
+ private static final Map<ServerPlayer, Pair<ResourceLocation, BlockPos>> playerWatchBlockPos = new HashMap<>();
|
|
+ private static final Map<ServerPlayer, Pair<ResourceLocation, Entity>> playerWatchEntity = new HashMap<>();
|
|
+ private static final Map<Pair<ResourceLocation, BlockPos>, Set<ServerPlayer>> blockPosWatchPlayerSet = new HashMap<>();
|
|
+ private static final Map<Pair<ResourceLocation, Entity>, Set<ServerPlayer>> entityWatchPlayerSet = new HashMap<>();
|
|
+ private static final MutablePair<ResourceLocation, Entity> ResourceLocationEntityPair = new MutablePair<>();
|
|
+ private static final MutablePair<ResourceLocation, BlockPos> ResourceLocationBlockPosPair = new MutablePair<>();
|
|
+
|
|
+ @Contract("_ -> new")
|
|
+ public static @NotNull ResourceLocation id(String path) {
|
|
+ return new ResourceLocation(PROTOCOL_ID, path);
|
|
+ }
|
|
+
|
|
+ public static void enablePcaSyncProtocol(@NotNull ServerPlayer player) {
|
|
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
|
+ ProtocolUtils.sendPayloadPacket(player, ENABLE_PCA_SYNC_PROTOCOL, buf);
|
|
+ lock.lock();
|
|
+ lock.unlock();
|
|
+ }
|
|
+
|
|
+ public static void disablePcaSyncProtocol(@NotNull ServerPlayer player) {
|
|
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
|
+ ProtocolUtils.sendPayloadPacket(player, DISABLE_PCA_SYNC_PROTOCOL, buf);
|
|
+ }
|
|
+
|
|
+ public static void updateEntity(@NotNull ServerPlayer player, @NotNull Entity entity) {
|
|
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
|
+ buf.writeResourceLocation(entity.getLevel().dimension().location());
|
|
+ buf.writeInt(entity.getId());
|
|
+ buf.writeNbt(entity.saveWithoutId(new CompoundTag()));
|
|
+ ProtocolUtils.sendPayloadPacket(player, UPDATE_ENTITY, buf);
|
|
+ }
|
|
+
|
|
+ public static void updateBlockEntity(@NotNull ServerPlayer player, @NotNull BlockEntity blockEntity) {
|
|
+ Level world = blockEntity.getLevel();
|
|
+
|
|
+ if (world == null) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
|
+ buf.writeResourceLocation(world.dimension().location());
|
|
+ buf.writeBlockPos(blockEntity.getBlockPos());
|
|
+ buf.writeNbt(blockEntity.saveWithId());
|
|
+ ProtocolUtils.sendPayloadPacket(player, UPDATE_BLOCK_ENTITY, buf);
|
|
+ }
|
|
+
|
|
+ private static final Map<ResourceLocation, TriConsumer<MinecraftServer, ServerPlayer, FriendlyByteBuf>> globalReceivers = new HashMap<>();
|
|
+
|
|
+ private static void registerGlobalReceiver(ResourceLocation identifier, TriConsumer<MinecraftServer, ServerPlayer, FriendlyByteBuf> consumer) {
|
|
+ globalReceivers.put(identifier, consumer);
|
|
+ }
|
|
+
|
|
+ public static void handlePacket(MinecraftServer server, ServerPlayer player, @NotNull ServerboundCustomPayloadPacket packet) {
|
|
+ globalReceivers.getOrDefault(
|
|
+ packet.identifier, ((server1, player1, buf) -> LeavesLogger.LOGGER.severe("NullPotion"))
|
|
+ ).accept(server, player, packet.data);
|
|
+ }
|
|
+
|
|
+ public static void init() {
|
|
+ registerGlobalReceiver(SYNC_BLOCK_ENTITY, PcaSyncProtocol::syncBlockEntityHandler);
|
|
+ registerGlobalReceiver(SYNC_ENTITY, PcaSyncProtocol::syncEntityHandler);
|
|
+ registerGlobalReceiver(CANCEL_SYNC_BLOCK_ENTITY, PcaSyncProtocol::cancelSyncBlockEntityHandler);
|
|
+ registerGlobalReceiver(CANCEL_SYNC_ENTITY, PcaSyncProtocol::cancelSyncEntityHandler);
|
|
+ }
|
|
+
|
|
+ public static void onJoin(ServerPlayer player) {
|
|
+ if (LeavesConfig.pcaSyncProtocol) {
|
|
+ enablePcaSyncProtocol(player);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static void cancelSyncBlockEntityHandler(MinecraftServer server, ServerPlayer player,
|
|
+ FriendlyByteBuf buf) {
|
|
+ if (!LeavesConfig.pcaSyncProtocol) {
|
|
+ return;
|
|
+ }
|
|
+ PcaSyncProtocol.clearPlayerWatchBlock(player);
|
|
+ }
|
|
+
|
|
+ private static void cancelSyncEntityHandler(MinecraftServer server, ServerPlayer player,
|
|
+ FriendlyByteBuf buf) {
|
|
+ if (!LeavesConfig.pcaSyncProtocol) {
|
|
+ return;
|
|
+ }
|
|
+ PcaSyncProtocol.clearPlayerWatchEntity(player);
|
|
+ }
|
|
+
|
|
+ private static void syncBlockEntityHandler(MinecraftServer server, ServerPlayer player,
|
|
+ FriendlyByteBuf buf) {
|
|
+ if (!LeavesConfig.pcaSyncProtocol) {
|
|
+ return;
|
|
+ }
|
|
+ BlockPos pos = buf.readBlockPos();
|
|
+ ServerLevel world = player.getLevel();
|
|
+ BlockState blockState = world.getBlockState(pos);
|
|
+ clearPlayerWatchData(player);
|
|
+
|
|
+ BlockEntity blockEntityAdj = null;
|
|
+ if (blockState.getBlock() instanceof ChestBlock) {
|
|
+ if (blockState.getValue(ChestBlock.TYPE) != ChestType.SINGLE) {
|
|
+ BlockPos posAdj = pos.offset(ChestBlock.getConnectedDirection(blockState).getNormal());
|
|
+ // The method in World now checks that the caller is from the same thread...
|
|
+ blockEntityAdj = world.getChunk(posAdj).getBlockEntity(posAdj);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (blockEntityAdj != null) {
|
|
+ updateBlockEntity(player, blockEntityAdj);
|
|
+ }
|
|
+
|
|
+ // The method in World now checks that the caller is from the same thread...
|
|
+ BlockEntity blockEntity = world.getChunk(pos).getBlockEntity(pos);
|
|
+ if (blockEntity != null) {
|
|
+ updateBlockEntity(player, blockEntity);
|
|
+ }
|
|
+
|
|
+ Pair<ResourceLocation, BlockPos> pair = new ImmutablePair<>(player.getLevel().dimension().location(), pos);
|
|
+ lock.lock();
|
|
+ playerWatchBlockPos.put(player, pair);
|
|
+ if (!blockPosWatchPlayerSet.containsKey(pair)) {
|
|
+ blockPosWatchPlayerSet.put(pair, new HashSet<>());
|
|
+ }
|
|
+ blockPosWatchPlayerSet.get(pair).add(player);
|
|
+ lock.unlock();
|
|
+ }
|
|
+
|
|
+ private static void syncEntityHandler(MinecraftServer server, ServerPlayer player,
|
|
+ FriendlyByteBuf buf) {
|
|
+ if (!LeavesConfig.pcaSyncProtocol) {
|
|
+ return;
|
|
+ }
|
|
+ int entityId = buf.readInt();
|
|
+ ServerLevel world = player.getLevel();
|
|
+ Entity entity = world.getEntity(entityId);
|
|
+ if (entity != null) {
|
|
+ clearPlayerWatchData(player);
|
|
+ if (entity instanceof Player) {
|
|
+ if (LeavesConfig.pcaSyncPlayerEntity.equals("NOBODY")) {
|
|
+ return;
|
|
+ } else if (LeavesConfig.pcaSyncPlayerEntity.equals("BOT")) {
|
|
+ if (!(entity instanceof ServerBot)) {
|
|
+ return;
|
|
+ }
|
|
+ } else if (LeavesConfig.pcaSyncPlayerEntity.equals("OPS")) {
|
|
+ if (!(entity instanceof ServerBot) && server.getProfilePermissions(player.getGameProfile()) < 2) {
|
|
+ return;
|
|
+ }
|
|
+ } else if (LeavesConfig.pcaSyncPlayerEntity.equals("OPS_AND_SELF")) {
|
|
+ if (!(entity instanceof ServerBot) &&
|
|
+ server.getProfilePermissions(player.getGameProfile()) < 2 &&
|
|
+ entity != player) {
|
|
+ return;
|
|
+ }
|
|
+ } else if (!LeavesConfig.pcaSyncPlayerEntity.equals("EVERYONE")) {
|
|
+ // wtf????
|
|
+ LeavesLogger.LOGGER.warning("pcaSyncPlayerEntity wtf???");
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ updateEntity(player, entity);
|
|
+
|
|
+ Pair<ResourceLocation, Entity> pair = new ImmutablePair<>(entity.getLevel().dimension().location(), entity);
|
|
+ lock.lock();
|
|
+ playerWatchEntity.put(player, pair);
|
|
+ if (!entityWatchPlayerSet.containsKey(pair)) {
|
|
+ entityWatchPlayerSet.put(pair, new HashSet<>());
|
|
+ }
|
|
+ entityWatchPlayerSet.get(pair).add(player);
|
|
+ lock.unlock();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static MutablePair<ResourceLocation, Entity> getResourceLocationEntityPair(ResourceLocation ResourceLocation, Entity entity) {
|
|
+ pairLock.lock();
|
|
+ ResourceLocationEntityPair.setLeft(ResourceLocation);
|
|
+ ResourceLocationEntityPair.setRight(entity);
|
|
+ pairLock.unlock();
|
|
+ return ResourceLocationEntityPair;
|
|
+ }
|
|
+
|
|
+ private static MutablePair<ResourceLocation, BlockPos> getResourceLocationBlockPosPair(ResourceLocation ResourceLocation, BlockPos pos) {
|
|
+ pairLock.lock();
|
|
+ ResourceLocationBlockPosPair.setLeft(ResourceLocation);
|
|
+ ResourceLocationBlockPosPair.setRight(pos);
|
|
+ pairLock.unlock();
|
|
+ return ResourceLocationBlockPosPair;
|
|
+ }
|
|
+
|
|
+ private static @Nullable Set<ServerPlayer> getWatchPlayerList(@NotNull Entity entity) {
|
|
+ return entityWatchPlayerSet.get(getResourceLocationEntityPair(entity.getLevel().dimension().location(), entity));
|
|
+ }
|
|
+
|
|
+ private static @Nullable Set<ServerPlayer> getWatchPlayerList(@NotNull Level world, @NotNull BlockPos blockPos) {
|
|
+ return blockPosWatchPlayerSet.get(getResourceLocationBlockPosPair(world.dimension().location(), blockPos));
|
|
+ }
|
|
+
|
|
+ public static boolean syncEntityToClient(@NotNull Entity entity) {
|
|
+ if (entity.getLevel().isClientSide()) {
|
|
+ return false;
|
|
+ }
|
|
+ lock.lock();
|
|
+ Set<ServerPlayer> playerList = getWatchPlayerList(entity);
|
|
+ boolean ret = false;
|
|
+ if (playerList != null) {
|
|
+ for (ServerPlayer player : playerList) {
|
|
+ updateEntity(player, entity);
|
|
+ ret = true;
|
|
+ }
|
|
+ }
|
|
+ lock.unlock();
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ public static boolean syncBlockEntityToClient(@NotNull BlockEntity blockEntity) {
|
|
+ boolean ret = false;
|
|
+ Level world = blockEntity.getLevel();
|
|
+ BlockPos pos = blockEntity.getBlockPos();
|
|
+ if (world != null) {
|
|
+ if (world.isClientSide()) {
|
|
+ return false;
|
|
+ }
|
|
+ BlockState blockState = world.getBlockState(pos);
|
|
+ lock.lock();
|
|
+ Set<ServerPlayer> playerList = getWatchPlayerList(world, blockEntity.getBlockPos());
|
|
+
|
|
+ Set<ServerPlayer> playerListAdj = null;
|
|
+
|
|
+ if (blockState.getBlock() instanceof ChestBlock) {
|
|
+ if (blockState.getValue(ChestBlock.TYPE) != ChestType.SINGLE) {
|
|
+ BlockPos posAdj = pos.offset(ChestBlock.getConnectedDirection(blockState).getNormal());
|
|
+ playerListAdj = getWatchPlayerList(world, posAdj);
|
|
+ }
|
|
+ }
|
|
+ if (playerListAdj != null) {
|
|
+ if (playerList == null) {
|
|
+ playerList = playerListAdj;
|
|
+ } else {
|
|
+ playerList.addAll(playerListAdj);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (playerList != null) {
|
|
+ for (ServerPlayer player : playerList) {
|
|
+ updateBlockEntity(player, blockEntity);
|
|
+ ret = true;
|
|
+ }
|
|
+ }
|
|
+ lock.unlock();
|
|
+ }
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ private static void clearPlayerWatchEntity(ServerPlayer player) {
|
|
+ lock.lock();
|
|
+ Pair<ResourceLocation, Entity> pair = playerWatchEntity.get(player);
|
|
+ if (pair != null) {
|
|
+ Set<ServerPlayer> playerSet = entityWatchPlayerSet.get(pair);
|
|
+ playerSet.remove(player);
|
|
+ if (playerSet.isEmpty()) {
|
|
+ entityWatchPlayerSet.remove(pair);
|
|
+ }
|
|
+ playerWatchEntity.remove(player);
|
|
+ }
|
|
+ lock.unlock();
|
|
+ }
|
|
+
|
|
+ private static void clearPlayerWatchBlock(ServerPlayer player) {
|
|
+ lock.lock();
|
|
+ Pair<ResourceLocation, BlockPos> pair = playerWatchBlockPos.get(player);
|
|
+ if (pair != null) {
|
|
+ Set<ServerPlayer> playerSet = blockPosWatchPlayerSet.get(pair);
|
|
+ playerSet.remove(player);
|
|
+ if (playerSet.isEmpty()) {
|
|
+ blockPosWatchPlayerSet.remove(pair);
|
|
+ }
|
|
+ playerWatchBlockPos.remove(player);
|
|
+ }
|
|
+ lock.unlock();
|
|
+ }
|
|
+
|
|
+ public static void disablePcaSyncProtocolGlobal() {
|
|
+ lock.lock();
|
|
+ playerWatchBlockPos.clear();
|
|
+ playerWatchEntity.clear();
|
|
+ blockPosWatchPlayerSet.clear();
|
|
+ entityWatchPlayerSet.clear();
|
|
+ lock.unlock();
|
|
+ for (ServerPlayer player : MinecraftServer.getServer().getPlayerList().getPlayers()) {
|
|
+ disablePcaSyncProtocol(player);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public static void enablePcaSyncProtocolGlobal() {
|
|
+ for (ServerPlayer player : MinecraftServer.getServer().getPlayerList().getPlayers()) {
|
|
+ enablePcaSyncProtocol(player);
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
+ public static void clearPlayerWatchData(ServerPlayer player) {
|
|
+ PcaSyncProtocol.clearPlayerWatchBlock(player);
|
|
+ PcaSyncProtocol.clearPlayerWatchEntity(player);
|
|
+ }
|
|
+}
|