9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-30 04:19:27 +00:00

方块实体1

This commit is contained in:
XiaoMoMi
2025-09-02 04:34:18 +08:00
parent 0b05473df4
commit d4ca37a3e1
35 changed files with 545 additions and 168 deletions

View File

@@ -73,7 +73,7 @@ public class BlockItemBehavior extends BlockBoundItemBehavior {
return InteractionResult.FAIL;
}
if (!context.canPlace()) {
return InteractionResult.FAIL;
return InteractionResult.PASS;
}
Player player = context.getPlayer();

View File

@@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.item.recipe.Recipe;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.plugin.locale.MessageConstants;
import net.momirealms.craftengine.core.util.ItemUtils;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -30,7 +31,7 @@ public class SearchRecipePlayerCommand extends BukkitCommandFeature<CommandSende
Player player = context.sender();
BukkitServerPlayer serverPlayer = plugin().adapt(player);
Item<?> item = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
if (item == null) {
if (ItemUtils.isEmpty(item)) {
handleFeedback(context, MessageConstants.COMMAND_SEARCH_RECIPE_NO_ITEM);
return;
}

View File

@@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.item.recipe.Recipe;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.plugin.locale.MessageConstants;
import net.momirealms.craftengine.core.util.ItemUtils;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -30,7 +31,7 @@ public class SearchUsagePlayerCommand extends BukkitCommandFeature<CommandSender
Player player = context.sender();
BukkitServerPlayer serverPlayer = plugin().adapt(player);
Item<?> item = serverPlayer.getItemInHand(InteractionHand.MAIN_HAND);
if (item.isEmpty()) {
if (ItemUtils.isEmpty(item)) {
handleFeedback(context, MessageConstants.COMMAND_SEARCH_USAGE_NO_ITEM);
return;
}

View File

@@ -1,15 +1,10 @@
package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import org.bukkit.Location;
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.incendo.cloud.Command;
import org.incendo.cloud.parser.standard.IntegerParser;
public class TestCommand extends BukkitCommandFeature<CommandSender> {
@@ -20,22 +15,9 @@ public class TestCommand extends BukkitCommandFeature<CommandSender> {
@Override
public Command.Builder<? extends CommandSender> assembleCommand(org.incendo.cloud.CommandManager<CommandSender> manager, Command.Builder<CommandSender> builder) {
return builder
.required("start", IntegerParser.integerParser(0))
.senderType(Player.class)
.handler(context -> {
Player sender = context.sender();
int start = context.get("start");
int x = sender.getChunk().getX() * 16;
int z = sender.getChunk().getZ() * 16;
int y = (sender.getLocation().getBlockY() / 16) * 16;
for (int a = 0; a < 16; a++) {
for (int b = 0; b < 16; b++) {
for (int c = 0; c < 16; c++) {
BlockData blockData = BlockStateUtils.fromBlockData(BlockStateUtils.idToBlockState(start + a + b * 16 + c * 256));
sender.getWorld().setBlockData(new Location(sender.getWorld(), x + a, y + b, z + c), blockData);
}
}
}
// DO NOT PUSH ANY CODE FOR TEST COMMAND
// 禁止推送含有实现的Test指令
});
}

View File

@@ -64,6 +64,7 @@ import net.momirealms.craftengine.core.plugin.network.*;
import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider;
import net.momirealms.craftengine.core.util.*;
import net.momirealms.craftengine.core.world.*;
import net.momirealms.craftengine.core.world.chunk.ChunkStatus;
import net.momirealms.craftengine.core.world.chunk.Palette;
import net.momirealms.craftengine.core.world.chunk.PalettedContainer;
import net.momirealms.craftengine.core.world.chunk.packet.BlockEntityData;
@@ -263,11 +264,11 @@ public class PacketConsumers {
FriendlyByteBuf buf = event.getBuffer();
if (VersionHelper.isOrAbove1_20_2()) {
long chunkPos = buf.readLong();
user.setChunkTrackStatus(new ChunkPos(chunkPos), false);
user.removeTrackedChunk(chunkPos);
} else {
int x = buf.readInt();
int y = buf.readInt();
user.setChunkTrackStatus(ChunkPos.of(x, y), false);
user.removeTrackedChunk(ChunkPos.asLong(x, y));
}
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundForgetLevelChunkPacket", e);
@@ -280,7 +281,6 @@ public class PacketConsumers {
FriendlyByteBuf buf = event.getBuffer();
int chunkX = buf.readInt();
int chunkZ = buf.readInt();
player.setChunkTrackStatus(ChunkPos.of(chunkX, chunkZ), true);
boolean named = !VersionHelper.isOrAbove1_20_2();
// ClientboundLevelChunkPacketData
int heightmapsCount = 0;
@@ -366,6 +366,9 @@ public class PacketConsumers {
}
buffer = newBuf.array();
}
// 开始修改
event.setChanged(true);
buf.clear();
buf.writeVarInt(event.packetID());
buf.writeInt(chunkX);
@@ -394,7 +397,10 @@ public class PacketConsumers {
buf.writeBitSet(emptyBlockYMask);
buf.writeByteArrayList(skyUpdates);
buf.writeByteArrayList(blockUpdates);
event.setChanged(true);
ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
// 记录加载的区块
player.addTrackedChunk(chunkPos.longKey, new ChunkStatus());
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to handle ClientboundLevelChunkWithLightPacket", e);
}

View File

@@ -1,9 +1,9 @@
package net.momirealms.craftengine.bukkit.plugin.network.payload.protocol;
import net.momirealms.craftengine.core.plugin.network.ModPacket;
import net.momirealms.craftengine.bukkit.plugin.network.payload.PayloadHelper;
import net.momirealms.craftengine.core.plugin.network.codec.NetworkCodec;
import net.momirealms.craftengine.core.plugin.network.ModPacket;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.plugin.network.codec.NetworkCodec;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.Key;

View File

@@ -2,8 +2,8 @@ package net.momirealms.craftengine.bukkit.plugin.network.payload.protocol;
import net.momirealms.craftengine.core.plugin.network.ModPacket;
import net.momirealms.craftengine.core.plugin.network.codec.NetworkCodec;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.plugin.network.codec.NetworkCodec;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.IntIdentityList;

View File

@@ -3,10 +3,10 @@ package net.momirealms.craftengine.bukkit.plugin.network.payload.protocol;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TranslationArgument;
import net.momirealms.craftengine.core.plugin.network.ModPacket;
import net.momirealms.craftengine.core.plugin.network.codec.NetworkCodec;
import net.momirealms.craftengine.bukkit.util.RegistryUtils;
import net.momirealms.craftengine.core.plugin.network.ModPacket;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.plugin.network.codec.NetworkCodec;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.IntIdentityList;

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.bukkit.plugin.user;
import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable;
import com.google.common.collect.Lists;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
@@ -35,9 +36,9 @@ import net.momirealms.craftengine.core.util.IntIdentityList;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.BlockPos;
import net.momirealms.craftengine.core.world.ChunkPos;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldEvents;
import net.momirealms.craftengine.core.world.chunk.ChunkStatus;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeInstance;
@@ -113,11 +114,9 @@ public class BukkitServerPlayer extends Player {
// cooldown data
private CooldownData cooldownData;
// tracked chunks
private final Set<ChunkPos> trackedChunks = Collections.synchronizedSet(new HashSet<>());
// relighted chunks
private final Set<ChunkPos> relightedChunks = Collections.synchronizedSet(new HashSet<>());
private ConcurrentLong2ReferenceChainedHashTable<ChunkStatus> trackedChunks;
// entity view
private final Map<Integer, EntityPacketHandler> entityTypeView = new ConcurrentHashMap<>();
private Map<Integer, EntityPacketHandler> entityTypeView;
public BukkitServerPlayer(BukkitCraftEngine plugin, @Nullable Channel channel) {
this.channel = channel;
@@ -139,6 +138,8 @@ public class BukkitServerPlayer extends Player {
this.uuid = player.getUniqueId();
this.name = player.getName();
byte[] bytes = player.getPersistentDataContainer().get(KeyUtils.toNamespacedKey(CooldownData.COOLDOWN_KEY), PersistentDataType.BYTE_ARRAY);
this.trackedChunks = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(768, 0.5f);
this.entityTypeView = new ConcurrentHashMap<>(256);
try {
this.cooldownData = CooldownData.fromBytes(bytes);
} catch (IOException e) {
@@ -1050,17 +1051,23 @@ public class BukkitServerPlayer extends Player {
}
@Override
public boolean isChunkTracked(ChunkPos chunkPos) {
return this.trackedChunks.contains(chunkPos);
public boolean isChunkTracked(long chunkPos) {
return this.trackedChunks.containsKey(chunkPos);
}
@Override
public void setChunkTrackStatus(ChunkPos chunkPos, boolean tracked) {
if (tracked) {
this.trackedChunks.add(chunkPos);
} else {
this.trackedChunks.remove(chunkPos);
}
public ChunkStatus getTrackedChunk(long chunkPos) {
return this.trackedChunks.get(chunkPos);
}
@Override
public void addTrackedChunk(long chunkPos, ChunkStatus chunkStatus) {
this.trackedChunks.put(chunkPos, chunkStatus);
}
@Override
public void removeTrackedChunk(long chunkPos) {
this.trackedChunks.remove(chunkPos);
}
@Override

View File

@@ -36,4 +36,42 @@ public final class LightUtils {
CraftEngine.instance().logger().warn("Could not update light for world " + world.getName(), e);
}
}
//
// public static void relightChunk(BukkitServerPlayer player, ChunkPos pos) {
// long chunkKey = pos.longKey;
// ChunkStatus status = player.getTrackedChunk(chunkKey);
// // 不处理未加载区块
// if (status == null || status.relighted()) return;
// for (ChunkPos anotherPos : pos.adjacentChunkPos()) {
// // 要求周围区块必须都加载
// if (player.getTrackedChunk(anotherPos.longKey) == null) {
// return;
// }
// }
// status.setRelighted(true);
// net.momirealms.craftengine.core.world.World world = player.world();
// Object serverLevel = world.serverWorld();
// Object chunkSource = FastNMS.INSTANCE.method$ServerLevel$getChunkSource(serverLevel);
// Object chunkHolder = FastNMS.INSTANCE.method$ServerChunkCache$getVisibleChunkIfPresent(chunkSource, chunkKey);
// if (chunkHolder == null) return;
// CEWorld ceWorld = BukkitWorldManager.instance().getWorld(world.uuid());
// CEChunk ceChunk = ceWorld.getChunkAtIfLoaded(chunkKey);
// if (ceChunk == null) return;
// CESection[] sections = ceChunk.sections();
// BitSet bitSet = new BitSet();
// for (int i = 0; i < sections.length; i++) {
// if (!sections[i].statesContainer().isEmpty()) {
// bitSet.set(i);
// }
// }
// if (bitSet.isEmpty()) return;
// try {
// Object lightEngine = CoreReflections.field$ChunkHolder$lightEngine.get(chunkHolder);
// Object chunkPos = FastNMS.INSTANCE.constructor$ChunkPos((int) chunkKey, (int) (chunkKey >> 32));
// Object lightPacket = FastNMS.INSTANCE.constructor$ClientboundLightUpdatePacket(chunkPos, lightEngine, bitSet, bitSet);
// player.sendPacket(lightPacket, false);
// } catch (Throwable t) {
// CraftEngine.instance().logger().warn("Could not send relight packet for " + player.name() + " at " + player.world().name() + " " + pos.x + "," + pos.z, t);
// }
// }
}

View File

@@ -23,6 +23,7 @@ public class BukkitCEWorld extends CEWorld {
@Override
public void tick() {
super.tick();
HashSet<SectionPos> poses;
synchronized (super.updatedSectionSet) {
poses = new HashSet<>(super.updatedSectionSet);