9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-30 20:39:10 +00:00

综合更新

This commit is contained in:
XiaoMoMi
2025-05-26 22:56:55 +08:00
parent 4951f37e8f
commit f08544f82e
15 changed files with 91 additions and 76 deletions

View File

@@ -73,7 +73,13 @@ public class BukkitCustomBlock extends AbstractCustomBlock {
BlockStateUtils.setHardness(mcBlockState, settings.hardness());
BlockStateUtils.setPushReaction(mcBlockState, settings.pushReaction());
BlockStateUtils.setReplaceable(mcBlockState, settings.replaceable());
BlockStateUtils.setCanOcclude(mcBlockState, settings.canOcclude());
if (settings.canOcclude() == Tristate.TRUE) {
BlockStateUtils.setCanOcclude(mcBlockState, true);
} else if (settings.canOcclude() == Tristate.FALSE) {
BlockStateUtils.setCanOcclude(mcBlockState, false);
} else {
BlockStateUtils.setCanOcclude(mcBlockState, BlockStateUtils.isOcclude(state.vanillaBlockState().handle()));
}
if (settings.isRedstoneConductor() == Tristate.TRUE) {
BlockStateUtils.setIsRedstoneConductor(mcBlockState, StatePredicate.alwaysTrue());
} else if (settings.isRedstoneConductor() == Tristate.FALSE) {
@@ -138,6 +144,8 @@ public class BukkitCustomBlock extends AbstractCustomBlock {
}
// set random tick later
BlockStateUtils.setIsRandomlyTicking(mcBlockState, settings.isRandomlyTicking());
// set propagates skylight
BlockStateUtils.setPropagatesSkylightDown(mcBlockState, settings.propagatesSkylightDown());
// bind tags
Object holder = BukkitCraftEngine.instance().blockManager().getMinecraftBlockHolder(state.customBlockState().registryId());
Set<Object> tags = new HashSet<>();

View File

@@ -23,18 +23,18 @@ import java.util.*;
public class BushBlockBehavior extends AbstractCanSurviveBlockBehavior {
public static final Factory FACTORY = new Factory();
protected final List<Object> tagsCanSurviveOn;
protected final Set<Object> blocksCansSurviveOn;
protected final Set<Object> blockStatesCanSurviveOn;
protected final Set<String> customBlocksCansSurviveOn;
protected final boolean any;
protected final boolean blacklistMode;
protected final boolean stackable;
public BushBlockBehavior(CustomBlock block, int delay, boolean stackable, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
public BushBlockBehavior(CustomBlock block, int delay, boolean blacklist, boolean stackable, List<Object> tagsCanSurviveOn, Set<Object> blockStatesCanSurviveOn, Set<String> customBlocksCansSurviveOn) {
super(block, delay);
this.blacklistMode = blacklist;
this.stackable = stackable;
this.tagsCanSurviveOn = tagsCanSurviveOn;
this.blocksCansSurviveOn = blocksCansSurviveOn;
this.blockStatesCanSurviveOn = blockStatesCanSurviveOn;
this.customBlocksCansSurviveOn = customBlocksCansSurviveOn;
this.any = this.tagsCanSurviveOn.isEmpty() && this.blocksCansSurviveOn.isEmpty() && this.customBlocksCansSurviveOn.isEmpty();
}
public static class Factory implements BlockBehaviorFactory {
@@ -44,7 +44,8 @@ public class BushBlockBehavior extends AbstractCanSurviveBlockBehavior {
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments, false);
boolean stackable = (boolean) arguments.getOrDefault("stackable", false);
int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay");
return new BushBlockBehavior(block, delay, stackable, tuple.left(), tuple.mid(), tuple.right());
boolean blacklistMode = (boolean) arguments.getOrDefault("blacklist", false);
return new BushBlockBehavior(block, delay, blacklistMode, stackable, tuple.left(), tuple.mid(), tuple.right());
}
}
@@ -85,35 +86,30 @@ public class BushBlockBehavior extends AbstractCanSurviveBlockBehavior {
}
protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) throws ReflectiveOperationException {
if (this.any) {
return belowState != Reflections.instance$Blocks$AIR$defaultState;
}
for (Object tag : this.tagsCanSurviveOn) {
if ((boolean) Reflections.method$BlockStateBase$hasTag.invoke(belowState, tag)) {
return true;
return !this.blacklistMode;
}
}
int id = BlockStateUtils.blockStateToId(belowState);
if (BlockStateUtils.isVanillaBlock(id)) {
if (!this.blocksCansSurviveOn.isEmpty() && this.blocksCansSurviveOn.contains(belowState)) {
return true;
if (!this.blockStatesCanSurviveOn.isEmpty() && this.blockStatesCanSurviveOn.contains(belowState)) {
return !this.blacklistMode;
}
} else {
ImmutableBlockState belowCustomState = BukkitBlockManager.instance().getImmutableBlockState(id);
if (belowCustomState != null && !belowCustomState.isEmpty()) {
if (stackable) {
if (belowCustomState.owner().value() == super.customBlock) {
return true;
}
if (belowCustomState.owner().value() == super.customBlock) {
return this.stackable;
}
if (this.customBlocksCansSurviveOn.contains(belowCustomState.owner().value().id().toString())) {
return true;
return !this.blacklistMode;
}
if (this.customBlocksCansSurviveOn.contains(belowCustomState.toString())) {
return true;
return !this.blacklistMode;
}
}
}
return false;
return this.blacklistMode;
}
}

View File

@@ -14,8 +14,8 @@ import java.util.Set;
public class HangingBlockBehavior extends BushBlockBehavior {
public static final Factory FACTORY = new Factory();
public HangingBlockBehavior(CustomBlock block, int delay, boolean stackable, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
super(block, delay, stackable, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
public HangingBlockBehavior(CustomBlock block, int delay, boolean blacklist, boolean stackable, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
super(block, delay, blacklist, stackable, tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
}
@Override
@@ -35,7 +35,8 @@ public class HangingBlockBehavior extends BushBlockBehavior {
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments, true);
boolean stackable = (boolean) arguments.getOrDefault("stackable", false);
int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay");
return new HangingBlockBehavior(block, delay, stackable, tuple.left(), tuple.mid(), tuple.right());
boolean blacklistMode = (boolean) arguments.getOrDefault("blacklist", false);
return new HangingBlockBehavior(block, delay, blacklistMode, stackable, tuple.left(), tuple.mid(), tuple.right());
}
}
}

View File

@@ -5,23 +5,16 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.UpdateOption;
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
import net.momirealms.craftengine.core.block.properties.IntegerProperty;
import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.util.RandomUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.BlockPos;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.WorldEvents;
import net.momirealms.craftengine.core.world.WorldPosition;
import net.momirealms.craftengine.shared.block.BlockBehavior;
import java.util.Map;

View File

@@ -1,9 +1,10 @@
package net.momirealms.craftengine.bukkit.item.listener;
import com.saicone.rtag.RtagItem;
import net.kyori.adventure.text.Component;
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.item.LegacyItemWrapper;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
@@ -13,7 +14,6 @@ import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.UpdateOption;
import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.util.MCUtils;
import net.momirealms.craftengine.core.util.MiscUtils;
import org.bukkit.Material;
@@ -73,8 +73,8 @@ public class DebugStickListener implements Listener {
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true);
player.sendPacket(systemChatPacket, false);
} else {
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(itemInHand);
Object storedData = wrapped.getTag("craftengine:debug_stick_state");
LegacyItemWrapper wrapped = new LegacyItemWrapper(new RtagItem(itemInHand), itemInHand.getAmount());
Object storedData = wrapped.get("craftengine:debug_stick_state");
if (storedData == null) storedData = new HashMap<>();
if (storedData instanceof Map<?,?> map) {
Map<String, Object> data = MiscUtils.castToMap(map, false);
@@ -96,7 +96,7 @@ public class DebugStickListener implements Listener {
} else {
currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive());
data.put(blockId, currentProperty.name());
wrapped.setTag(data, "craftengine:debug_stick_state");
wrapped.set(data, "craftengine:debug_stick_state");
wrapped.load();
Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance(
ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select")

View File

@@ -29,6 +29,7 @@ import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.bukkit.util.NoteBlockChainUpdateUtils;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.block.BlockKeys;
@@ -56,7 +57,6 @@ import net.momirealms.craftengine.core.world.chunk.InjectedHolder;
import net.momirealms.craftengine.shared.ObjectHolder;
import net.momirealms.craftengine.shared.block.*;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -809,19 +809,18 @@ public class BukkitInjector {
// 如果先前不是空气则标记
if (!previous.isEmpty()) {
holder.ceChunk().setDirty(true);
}
if (Config.enableLightSystem() && Config.forceUpdateLight()) {
updateLightIfChanged(holder, previousState, newState, null, y, z, x);
if (Config.enableLightSystem()) {
updateLightIfChanged(holder, previous.vanillaBlockState().handle(), newState, y, z, x);
}
}
} else {
ImmutableBlockState immutableBlockState = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId);
ImmutableBlockState previousImmutableBlockState = section.setBlockState(x, y, z, immutableBlockState);
// 如果之前的自定义块(空气)和当前自定义块不同
if (previousImmutableBlockState != immutableBlockState) {
holder.ceChunk().setDirty(true);
if (Config.enableLightSystem() && !immutableBlockState.isEmpty()) {
updateLightIfChanged(holder, previousState, newState, immutableBlockState.vanillaBlockState().handle(), y, z, x);
}
if (previousImmutableBlockState == immutableBlockState) return;
holder.ceChunk().setDirty(true);
// 如果新方块的光照属性和客户端认为的不同
if (Config.enableLightSystem() && !immutableBlockState.isEmpty()) {
updateLightIfChanged(holder, immutableBlockState.vanillaBlockState().handle(), newState, y, z, x);
}
}
} catch (Exception e) {
@@ -829,13 +828,11 @@ public class BukkitInjector {
}
}
protected static void updateLightIfChanged(@This InjectedHolder thisObj, Object previousBlockState, Object newState, @Nullable Object clientSideNewState, int y, int z, int x) throws ReflectiveOperationException {
int previousLight = BlockStateUtils.getLightEmission(previousBlockState);
int newLight = BlockStateUtils.getLightEmission(newState);
if (previousLight != newLight || (clientSideNewState != null && (BlockStateUtils.isOcclude(newState) != BlockStateUtils.isOcclude(clientSideNewState)))) {
CEWorld world = thisObj.ceChunk().world();
protected static void updateLightIfChanged(@This InjectedHolder thisObj, Object oldState, Object newState, int y, int z, int x) {
CEWorld world = thisObj.ceChunk().world();
if (FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(oldState, newState, world.world().serverWorld(), LocationUtils.toBlockPos(x, y, z))) {
SectionPos sectionPos = thisObj.cePos();
List<SectionPos> pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, Math.max(newLight, previousLight));
List<SectionPos> pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, 15);
world.sectionLightUpdated(pos);
}
}

View File

@@ -189,6 +189,10 @@ public class BlockStateUtils {
Reflections.field$BlockStateBase$isRandomlyTicking.set(state, randomlyTicking);
}
public static void setPropagatesSkylightDown(Object state, boolean propagatesSkylightDown) throws ReflectiveOperationException {
Reflections.field$BlockStateBase$propagatesSkylightDown.set(state, propagatesSkylightDown);
}
public static void setReplaceable(Object state, boolean replaceable) throws ReflectiveOperationException {
Reflections.field$BlockStateBase$replaceable.set(state, replaceable);
}
@@ -205,7 +209,7 @@ public class BlockStateUtils {
Reflections.field$BlockStateBase$canOcclude.set(state, canOcclude);
}
public static boolean isOcclude(Object state) throws ReflectiveOperationException {
public static boolean isOcclude(Object state) {
return FastNMS.INSTANCE.method$BlockStateBase$canOcclude(state);
}

View File

@@ -2423,6 +2423,12 @@ public class Reflections {
)
);
public static final Field field$BlockStateBase$propagatesSkylightDown = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$BlockStateBase, boolean.class, 11
)
);
public static final Field field$BlockStateBase$requiresCorrectToolForDrops = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$BlockStateBase, boolean.class, 5