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

优化转化类行为目标状态

This commit is contained in:
XiaoMoMi
2025-10-06 16:42:25 +08:00
parent 1ee80df844
commit b74cb78ef4
12 changed files with 119 additions and 34 deletions

View File

@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.block;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils; import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.core.block.AbstractBlockStateWrapper; import net.momirealms.craftengine.core.block.AbstractBlockStateWrapper;
import net.momirealms.craftengine.core.block.BlockStateWrapper;
import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
@@ -30,6 +31,21 @@ public class BukkitCustomBlockStateWrapper extends AbstractBlockStateWrapper {
}).orElse(null); }).orElse(null);
} }
@Override
public BlockStateWrapper withProperty(String propertyName, String propertyValue) {
Optional<ImmutableBlockState> immutableBlockState = getImmutableBlockState();
if (immutableBlockState.isPresent()) {
Property<?> property = immutableBlockState.get().owner().value().getProperty(propertyName);
if (property != null) {
Comparable<?> value = property.valueByName(propertyValue);
if (value != null) {
return ImmutableBlockState.with(immutableBlockState.get(), property, value).customBlockState();
}
}
}
return this;
}
@Override @Override
public boolean hasProperty(String propertyName) { public boolean hasProperty(String propertyName) {
return getImmutableBlockState().map(state -> state.owner().value().getProperty(propertyName) != null).orElse(false); return getImmutableBlockState().map(state -> state.owner().value().getProperty(propertyName) != null).orElse(false);

View File

@@ -3,6 +3,8 @@ package net.momirealms.craftengine.bukkit.block;
import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils; import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.core.block.AbstractBlockStateWrapper; import net.momirealms.craftengine.core.block.AbstractBlockStateWrapper;
import net.momirealms.craftengine.core.block.BlockRegistryMirror;
import net.momirealms.craftengine.core.block.BlockStateWrapper;
import net.momirealms.craftengine.core.block.StatePropertyAccessor; import net.momirealms.craftengine.core.block.StatePropertyAccessor;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
@@ -33,4 +35,11 @@ public class BukkitVanillaBlockStateWrapper extends AbstractBlockStateWrapper {
public String getAsString() { public String getAsString() {
return BlockStateUtils.fromBlockData(super.blockState).getAsString(); return BlockStateUtils.fromBlockData(super.blockState).getAsString();
} }
@Override
public BlockStateWrapper withProperty(String propertyName, String propertyValue) {
Object newState = this.accessor.withProperty(propertyName, propertyValue);
if (newState == super.blockState) return this;
return BlockRegistryMirror.byId(BlockStateUtils.blockStateToId(newState));
}
} }

View File

@@ -2,12 +2,14 @@ package net.momirealms.craftengine.bukkit.block.behavior;
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
import net.momirealms.craftengine.core.block.*; import net.momirealms.craftengine.core.block.*;
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.RandomUtils; import net.momirealms.craftengine.core.util.*;
import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.sparrow.nbt.CompoundTag;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@@ -15,23 +17,47 @@ import java.util.concurrent.Callable;
public class ChangeOverTimeBlockBehavior extends BukkitBlockBehavior { public class ChangeOverTimeBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory(); public static final Factory FACTORY = new Factory();
private final float changeSpeed; private final float changeSpeed;
private final Key nextBlock; private final String nextBlock;
private final LazyReference<BlockStateWrapper> lazyState;
private final List<String> excludedProperties;
public ChangeOverTimeBlockBehavior(CustomBlock customBlock, float changeSpeed, Key nextBlock) { public ChangeOverTimeBlockBehavior(CustomBlock customBlock, float changeSpeed, String nextBlock, List<String> excludedProperties) {
super(customBlock); super(customBlock);
this.changeSpeed = changeSpeed; this.changeSpeed = changeSpeed;
this.nextBlock = nextBlock; this.nextBlock = nextBlock;
this.excludedProperties = excludedProperties;
this.lazyState = LazyReference.lazyReference(() -> CraftEngine.instance().blockManager().createBlockState(this.nextBlock));
}
public String nextBlock() {
return nextBlock;
}
public BlockStateWrapper nextState() {
return this.lazyState.get();
}
public CompoundTag filter(CompoundTag properties) {
for (String property : this.excludedProperties) {
properties.remove(property);
}
return properties;
} }
@Override @Override
public void randomTick(Object thisBlock, Object[] args, Callable<Object> superMethod) throws ReflectiveOperationException { public void randomTick(Object thisBlock, Object[] args, Callable<Object> superMethod) {
if (RandomUtils.generateRandomFloat(0F, 1F) >= this.changeSpeed) return; if (RandomUtils.generateRandomFloat(0F, 1F) >= this.changeSpeed) return;
Optional<Object> nextState = BukkitBlockManager.instance().blockById(this.nextBlock) Object blockState = args[0];
.map(CustomBlock::defaultState) BlockStateUtils.getOptionalCustomBlockState(blockState).ifPresent(state -> {
.map(ImmutableBlockState::customBlockState) BlockStateWrapper nextState = this.nextState();
.map(BlockStateWrapper::literalObject); if (nextState == null) return;
if (nextState.isEmpty()) return; nextState = nextState.withProperties(filter(state.propertiesNbt()));
CraftBukkitReflections.method$CraftEventFactory$handleBlockFormEvent.invoke(null, args[1], args[2], nextState.get(), UpdateOption.UPDATE_ALL.flags()); try {
CraftBukkitReflections.method$CraftEventFactory$handleBlockFormEvent.invoke(null, args[1], args[2], nextState.literalObject(), UpdateOption.UPDATE_ALL.flags());
} catch (ReflectiveOperationException e) {
CraftEngine.instance().logger().warn("Failed to call block form event", e);
}
});
} }
public static class Factory implements BlockBehaviorFactory { public static class Factory implements BlockBehaviorFactory {
@@ -39,8 +65,9 @@ public class ChangeOverTimeBlockBehavior extends BukkitBlockBehavior {
@Override @Override
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) { public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
float changeSpeed = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("change-speed", 0.05688889F), "change-speed"); float changeSpeed = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("change-speed", 0.05688889F), "change-speed");
Key nextBlock = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.getOrDefault("next-block", "minecraft:air"), "warning.config.block.behavior.change_over_time.missing_next_block")); String nextBlock = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.getOrDefault("next-block", "minecraft:air"), "warning.config.block.behavior.change_over_time.missing_next_block");
return new ChangeOverTimeBlockBehavior(block, changeSpeed, nextBlock); List<String> excludedProperties = MiscUtils.getAsStringList(arguments.get("excluded-properties"));
return new ChangeOverTimeBlockBehavior(block, changeSpeed, nextBlock, excludedProperties);
} }
} }
} }

View File

@@ -1,40 +1,53 @@
package net.momirealms.craftengine.bukkit.block.behavior; package net.momirealms.craftengine.bukkit.block.behavior;
import net.momirealms.craftengine.core.block.BlockBehavior; import net.momirealms.craftengine.core.block.BlockBehavior;
import net.momirealms.craftengine.core.block.BlockStateWrapper;
import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.CustomBlock;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
import net.momirealms.craftengine.core.block.parser.BlockStateParser; import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.LazyReference; import net.momirealms.craftengine.core.util.LazyReference;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.sparrow.nbt.CompoundTag;
import java.util.List;
import java.util.Map; import java.util.Map;
public class StrippableBlockBehavior extends BukkitBlockBehavior { public class StrippableBlockBehavior extends BukkitBlockBehavior {
public static final Factory FACTORY = new Factory(); public static final Factory FACTORY = new Factory();
private final String stripped; private final String stripped;
private final LazyReference<ImmutableBlockState> lazyState; private final LazyReference<BlockStateWrapper> lazyState;
private final List<String> excludedProperties;
public StrippableBlockBehavior(CustomBlock block, String stripped) { public StrippableBlockBehavior(CustomBlock block, String stripped, List<String> excludedProperties) {
super(block); super(block);
this.stripped = stripped; this.stripped = stripped;
this.lazyState = LazyReference.lazyReference(() -> BlockStateParser.deserialize(this.stripped)); this.lazyState = LazyReference.lazyReference(() -> CraftEngine.instance().blockManager().createBlockState(this.stripped));
this.excludedProperties = excludedProperties;
} }
public String stripped() { public String stripped() {
return this.stripped; return this.stripped;
} }
public ImmutableBlockState strippedState() { public BlockStateWrapper strippedState() {
return this.lazyState.get(); return this.lazyState.get();
} }
public CompoundTag filter(CompoundTag properties) {
for (String property : this.excludedProperties) {
properties.remove(property);
}
return properties;
}
public static class Factory implements BlockBehaviorFactory { public static class Factory implements BlockBehaviorFactory {
@Override @Override
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) { public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
String stripped = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("stripped"), "warning.config.block.behavior.strippable.missing_stripped"); String stripped = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("stripped"), "warning.config.block.behavior.strippable.missing_stripped");
return new StrippableBlockBehavior(block, stripped); List<String> excludedProperties = MiscUtils.getAsStringList(arguments.get("excluded-properties"));
return new StrippableBlockBehavior(block, stripped, excludedProperties);
} }
} }
} }

View File

@@ -70,21 +70,19 @@ public class AxeItemBehavior extends ItemBehavior {
return InteractionResult.PASS; return InteractionResult.PASS;
} }
ImmutableBlockState newState = behaviorOptional.get().strippedState(); BlockStateWrapper newState = behaviorOptional.get().strippedState();
if (newState == null) { if (newState == null) {
CraftEngine.instance().logger().warn("stripped block " + behaviorOptional.get().stripped() + " does not exist"); CraftEngine.instance().logger().warn("stripped block " + behaviorOptional.get().stripped() + " does not exist");
return InteractionResult.FAIL; return InteractionResult.FAIL;
} }
BlockStateWrapper newState = newState.withProperties(behaviorOptional.get().filter(customState.propertiesNbt()));
newState = newState.with(customState.propertiesNbt());
BukkitExistingBlock clicked = (BukkitExistingBlock) context.getLevel().getBlockAt(context.getClickedPos()); BukkitExistingBlock clicked = (BukkitExistingBlock) context.getLevel().getBlockAt(context.getClickedPos());
org.bukkit.entity.Player bukkitPlayer = null; org.bukkit.entity.Player bukkitPlayer = null;
if (player != null) { if (player != null) {
bukkitPlayer = ((org.bukkit.entity.Player) player.platformPlayer()); bukkitPlayer = ((org.bukkit.entity.Player) player.platformPlayer());
// Call bukkit event // Call bukkit event
EntityChangeBlockEvent event = new EntityChangeBlockEvent(bukkitPlayer, clicked.block(), BlockStateUtils.fromBlockData(newState.customBlockState().literalObject())); EntityChangeBlockEvent event = new EntityChangeBlockEvent(bukkitPlayer, clicked.block(), BlockStateUtils.fromBlockData(newState.literalObject()));
if (EventUtils.fireAndCheckCancel(event)) { if (EventUtils.fireAndCheckCancel(event)) {
return InteractionResult.FAIL; return InteractionResult.FAIL;
} }
@@ -95,7 +93,7 @@ public class AxeItemBehavior extends ItemBehavior {
if (ItemUtils.isEmpty(item)) return InteractionResult.FAIL; if (ItemUtils.isEmpty(item)) return InteractionResult.FAIL;
BlockPos pos = context.getClickedPos(); BlockPos pos = context.getClickedPos();
context.getLevel().playBlockSound(Vec3d.atCenterOf(pos), AXE_STRIP_SOUND, 1, 1); context.getLevel().playBlockSound(Vec3d.atCenterOf(pos), AXE_STRIP_SOUND, 1, 1);
FastNMS.INSTANCE.method$LevelWriter$setBlock(context.getLevel().serverWorld(), LocationUtils.toBlockPos(pos), newState.customBlockState().literalObject(), UpdateOption.UPDATE_ALL_IMMEDIATE.flags()); FastNMS.INSTANCE.method$LevelWriter$setBlock(context.getLevel().serverWorld(), LocationUtils.toBlockPos(pos), newState.literalObject(), UpdateOption.UPDATE_ALL_IMMEDIATE.flags());
clicked.block().getWorld().sendGameEvent(bukkitPlayer, GameEvent.BLOCK_CHANGE, new Vector(pos.x(), pos.y(), pos.z())); clicked.block().getWorld().sendGameEvent(bukkitPlayer, GameEvent.BLOCK_CHANGE, new Vector(pos.x(), pos.y(), pos.z()));
Material material = MaterialUtils.getMaterial(item.vanillaId()); Material material = MaterialUtils.getMaterial(item.vanillaId());
if (bukkitPlayer != null) { if (bukkitPlayer != null) {
@@ -123,7 +121,7 @@ public class AxeItemBehavior extends ItemBehavior {
itemStack.damage(1, bukkitPlayer); itemStack.damage(1, bukkitPlayer);
} }
} }
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS_AND_CANCEL;
} }
public static class Factory implements ItemBehaviorFactory { public static class Factory implements ItemBehaviorFactory {

View File

@@ -1,8 +1,11 @@
package net.momirealms.craftengine.core.block; package net.momirealms.craftengine.core.block;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.sparrow.nbt.*;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Map;
public interface BlockStateWrapper extends Comparable<BlockStateWrapper> { public interface BlockStateWrapper extends Comparable<BlockStateWrapper> {
Object literalObject(); Object literalObject();
@@ -15,10 +18,27 @@ public interface BlockStateWrapper extends Comparable<BlockStateWrapper> {
boolean hasProperty(String propertyName); boolean hasProperty(String propertyName);
BlockStateWrapper withProperty(String propertyName, String propertyValue);
String getAsString(); String getAsString();
@Override @Override
default int compareTo(@NotNull BlockStateWrapper o) { default int compareTo(@NotNull BlockStateWrapper o) {
return Integer.compare(registryId(), o.registryId()); return Integer.compare(registryId(), o.registryId());
} }
default BlockStateWrapper withProperties(CompoundTag properties) {
BlockStateWrapper result = this;
for (Map.Entry<String, Tag> entry : properties.entrySet()) {
Tag value = entry.getValue();
if (value instanceof StringTag stringTag) {
result = result.withProperty(entry.getKey(), stringTag.getAsString());
} else if (value instanceof IntTag intTag) {
result = result.withProperty(entry.getKey(), String.valueOf(intTag.getAsInt()));
} else if (value instanceof ByteTag byteTag) {
result = result.withProperty(entry.getKey(), String.valueOf(byteTag.booleanValue()));
}
}
return result;
}
} }

View File

@@ -7,7 +7,6 @@ import net.momirealms.craftengine.core.block.entity.BlockEntityType;
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement;
import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig;
import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker; import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker;
import net.momirealms.craftengine.core.block.properties.EnumProperty;
import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.block.properties.Property;
import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.Item;

View File

@@ -1,5 +1,7 @@
package net.momirealms.craftengine.core.block; package net.momirealms.craftengine.core.block;
import org.jetbrains.annotations.NotNull;
import java.util.Collection; import java.util.Collection;
public interface StatePropertyAccessor { public interface StatePropertyAccessor {
@@ -11,4 +13,7 @@ public interface StatePropertyAccessor {
boolean hasProperty(String property); boolean hasProperty(String property);
<T> T getPropertyValue(String property); <T> T getPropertyValue(String property);
@NotNull
Object withProperty(String propertyName, String value);
} }

View File

@@ -6,7 +6,6 @@ import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import net.momirealms.sparrow.nbt.IntTag; import net.momirealms.sparrow.nbt.IntTag;
import net.momirealms.sparrow.nbt.NumericTag; import net.momirealms.sparrow.nbt.NumericTag;
import net.momirealms.sparrow.nbt.Tag; import net.momirealms.sparrow.nbt.Tag;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Direction;
import net.momirealms.craftengine.core.util.HorizontalDirection; import net.momirealms.craftengine.core.util.HorizontalDirection;
import net.momirealms.sparrow.nbt.Tag; import net.momirealms.sparrow.nbt.Tag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.HashMap; import java.util.HashMap;
@@ -155,7 +156,7 @@ public abstract class Property<T extends Comparable<T>> {
} }
@Override @Override
public String toString() { public @NotNull String toString() {
return this.property.name + "=" + this.property.valueName(this.value); return this.property.name + "=" + this.property.valueName(this.value);
} }
} }

View File

@@ -4,10 +4,8 @@ import com.google.common.collect.ImmutableMap;
import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.sparrow.nbt.StringTag; import net.momirealms.sparrow.nbt.StringTag;
import net.momirealms.sparrow.nbt.Tag; import net.momirealms.sparrow.nbt.Tag;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;

View File

@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
ahocorasick_version=0.6.3 ahocorasick_version=0.6.3
snake_yaml_version=2.5 snake_yaml_version=2.5
anti_grief_version=1.0.2 anti_grief_version=1.0.2
nms_helper_version=1.0.103 nms_helper_version=1.0.104
evalex_version=3.5.0 evalex_version=3.5.0
reactive_streams_version=1.0.4 reactive_streams_version=1.0.4
amazon_awssdk_version=2.34.5 amazon_awssdk_version=2.34.5