mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
refactor bush block
This commit is contained in:
@@ -34,6 +34,9 @@ blocks:
|
||||
push-reaction: DESTROY
|
||||
behavior:
|
||||
type: bush_block
|
||||
bottom-block-tags:
|
||||
- minecraft:dirt
|
||||
- minecraft:farmland
|
||||
loot:
|
||||
template: "default:loot_table/basic"
|
||||
arguments:
|
||||
|
||||
@@ -6,6 +6,7 @@ import net.momirealms.craftengine.shared.block.EmptyBlockBehavior;
|
||||
|
||||
public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key BUSH_BLOCK = Key.from("craftengine:bush_block");
|
||||
public static final Key HANGING_BLOCK = Key.from("craftengine:hanging_block");
|
||||
public static final Key FALLING_BLOCK = Key.from("craftengine:falling_block");
|
||||
public static final Key LEAVES_BLOCK = Key.from("craftengine:leaves_block");
|
||||
public static final Key STRIPPABLE_BLOCK = Key.from("craftengine:strippable_block");
|
||||
@@ -18,6 +19,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
register(FALLING_BLOCK, FallingBlockBehavior.FACTORY);
|
||||
register(BUSH_BLOCK, BushBlockBehavior.FACTORY);
|
||||
register(HANGING_BLOCK, HangingBlockBehavior.FACTORY);
|
||||
register(LEAVES_BLOCK, LeavesBlockBehavior.FACTORY);
|
||||
register(STRIPPABLE_BLOCK, StrippableBlockBehavior.FACTORY);
|
||||
register(SAPLING_BLOCK, SaplingBlockBehavior.FACTORY);
|
||||
|
||||
@@ -14,26 +14,29 @@ import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.loot.parameter.LootParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.Tuple;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.util.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class BushBlockBehavior extends AbstractBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
protected static final Object DIRT_TAG = BlockTags.getOrCreate(Key.of("minecraft", "dirt"));
|
||||
protected static final Object FARMLAND = BlockTags.getOrCreate(Key.of("minecraft", "farmland"));
|
||||
public static final BushBlockBehavior INSTANCE = new BushBlockBehavior(List.of(DIRT_TAG, FARMLAND));
|
||||
protected final List<Object> tagsCanSurviveOn;
|
||||
protected final Set<Object> blocksCansSurviveOn;
|
||||
protected final Set<String> customBlocksCansSurviveOn;
|
||||
protected final boolean any;
|
||||
|
||||
public BushBlockBehavior(List<Object> tagsCanSurviveOn) {
|
||||
public BushBlockBehavior(List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
|
||||
this.tagsCanSurviveOn = tagsCanSurviveOn;
|
||||
this.blocksCansSurviveOn = blocksCansSurviveOn;
|
||||
this.customBlocksCansSurviveOn = customBlocksCansSurviveOn;
|
||||
this.any = this.tagsCanSurviveOn.isEmpty() && this.blocksCansSurviveOn.isEmpty() && this.customBlocksCansSurviveOn.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,19 +85,41 @@ public class BushBlockBehavior extends AbstractBlockBehavior {
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
if (arguments.containsKey("bottom-block-tags")) {
|
||||
return new BushBlockBehavior(MiscUtils.getAsStringList(arguments.get("bottom-block-tags")).stream().map(it -> BlockTags.getOrCreate(Key.of(it))).toList());
|
||||
} else if (arguments.containsKey("tags")) {
|
||||
return new BushBlockBehavior(MiscUtils.getAsStringList(arguments.get("tags")).stream().map(it -> BlockTags.getOrCreate(Key.of(it))).toList());
|
||||
} else {
|
||||
return INSTANCE;
|
||||
}
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments);
|
||||
return new BushBlockBehavior(tuple.left(), tuple.mid(), tuple.right());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canSurvive(Object thisBlock, Object state, Object world, Object blockPos) throws ReflectiveOperationException {
|
||||
public static Tuple<List<Object>, Set<Object>, Set<String>> readTagsAndState(Map<String, Object> arguments) {
|
||||
List<Object> mcTags = new ArrayList<>();
|
||||
for (String tag : MiscUtils.getAsStringList(arguments.getOrDefault("bottom-block-tags", List.of()))) {
|
||||
mcTags.add(BlockTags.getOrCreate(Key.of(tag)));
|
||||
}
|
||||
Set<Object> mcBlocks = new HashSet<>();
|
||||
Set<String> customBlocks = new HashSet<>();
|
||||
for (String blockStateStr : MiscUtils.getAsStringList(arguments.getOrDefault("bottom-blocks", List.of()))) {
|
||||
int index = blockStateStr.indexOf('[');
|
||||
Key blockType = index != -1 ? Key.from(blockStateStr.substring(0, index)) : Key.from(blockStateStr);
|
||||
Material material = Registry.MATERIAL.get(new NamespacedKey(blockType.namespace(), blockType.value()));
|
||||
if (material != null) {
|
||||
if (index == -1) {
|
||||
// vanilla
|
||||
mcBlocks.addAll(BlockStateUtils.getAllVanillaBlockStates(blockType));
|
||||
} else {
|
||||
mcBlocks.add(BlockStateUtils.blockDataToBlockState(Bukkit.createBlockData(blockStateStr)));
|
||||
}
|
||||
} else {
|
||||
// custom maybe
|
||||
customBlocks.add(blockStateStr);
|
||||
}
|
||||
}
|
||||
return new Tuple<>(mcTags, mcBlocks, customBlocks);
|
||||
}
|
||||
|
||||
protected boolean canSurvive(Object thisBlock, Object state, Object world, Object blockPos) throws ReflectiveOperationException {
|
||||
int y = Reflections.field$Vec3i$y.getInt(blockPos);
|
||||
int x = Reflections.field$Vec3i$x.getInt(blockPos);
|
||||
int z = Reflections.field$Vec3i$z.getInt(blockPos);
|
||||
@@ -104,11 +129,28 @@ public class BushBlockBehavior extends AbstractBlockBehavior {
|
||||
}
|
||||
|
||||
protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) throws ReflectiveOperationException {
|
||||
if (this.any) return true;
|
||||
for (Object tag : this.tagsCanSurviveOn) {
|
||||
if ((boolean) Reflections.method$BlockStateBase$hasTag.invoke(belowState, tag)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
int id = BlockStateUtils.blockStateToId(belowState);
|
||||
if (BlockStateUtils.isVanillaBlock(id)) {
|
||||
if (!this.blocksCansSurviveOn.isEmpty() && this.blocksCansSurviveOn.contains(belowState)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
ImmutableBlockState previousState = BukkitBlockManager.instance().getImmutableBlockState(id);
|
||||
if (previousState != null && !previousState.isEmpty()) {
|
||||
if (this.customBlocksCansSurviveOn.contains(previousState.owner().value().id().toString())) {
|
||||
return true;
|
||||
}
|
||||
if (this.customBlocksCansSurviveOn.contains(previousState.toString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.util.Tuple;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class HangingBlockBehavior extends BushBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
|
||||
public HangingBlockBehavior(List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
|
||||
super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSurvive(Object thisBlock, Object state, Object world, Object blockPos) throws ReflectiveOperationException {
|
||||
int y = Reflections.field$Vec3i$y.getInt(blockPos);
|
||||
int x = Reflections.field$Vec3i$x.getInt(blockPos);
|
||||
int z = Reflections.field$Vec3i$z.getInt(blockPos);
|
||||
Object belowPos = Reflections.constructor$BlockPos.newInstance(x, y + 1, z);
|
||||
Object belowState = Reflections.method$BlockGetter$getBlockState.invoke(world, belowPos);
|
||||
return mayPlaceOn(belowState, world, belowPos);
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments);
|
||||
return new HangingBlockBehavior(tuple.left(), tuple.mid(), tuple.right());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,15 @@ import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class OnLiquidBlockBehavior extends BushBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final boolean onWater;
|
||||
private final boolean onLava;
|
||||
|
||||
public OnLiquidBlockBehavior(List<Object> tagsCanSurviveOn, boolean onWater, boolean onLava) {
|
||||
super(tagsCanSurviveOn);
|
||||
public OnLiquidBlockBehavior(boolean onWater, boolean onLava) {
|
||||
super(List.of(), Set.of(), Set.of());
|
||||
this.onWater = onWater;
|
||||
this.onLava = onLava;
|
||||
}
|
||||
@@ -33,7 +34,7 @@ public class OnLiquidBlockBehavior extends BushBlockBehavior {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
List<String> liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-type", List.of("water")));
|
||||
return new OnLiquidBlockBehavior(List.of(), liquidTypes.contains("water"), liquidTypes.contains("lava"));
|
||||
return new OnLiquidBlockBehavior(liquidTypes.contains("water"), liquidTypes.contains("lava"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@ package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.FeatureUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.UpdateOption;
|
||||
@@ -12,6 +15,7 @@ import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.RandomUtils;
|
||||
import net.momirealms.craftengine.core.util.Tuple;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
@@ -19,6 +23,7 @@ import org.bukkit.World;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class SaplingBlockBehavior extends BushBlockBehavior {
|
||||
@@ -27,8 +32,8 @@ public class SaplingBlockBehavior extends BushBlockBehavior {
|
||||
private final Property<Integer> stageProperty;
|
||||
private final double boneMealSuccessChance;
|
||||
|
||||
public SaplingBlockBehavior(Key feature, Property<Integer> stageProperty, List<Object> tagsCanSurviveOn, double boneMealSuccessChance) {
|
||||
super(tagsCanSurviveOn);
|
||||
public SaplingBlockBehavior(Key feature, Property<Integer> stageProperty, List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn, double boneMealSuccessChance) {
|
||||
super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
this.feature = feature;
|
||||
this.stageProperty = stageProperty;
|
||||
this.boneMealSuccessChance = boneMealSuccessChance;
|
||||
@@ -121,13 +126,8 @@ public class SaplingBlockBehavior extends BushBlockBehavior {
|
||||
throw new IllegalArgumentException("stage property not set for sapling");
|
||||
}
|
||||
double boneMealSuccessChance = MiscUtils.getAsDouble(arguments.getOrDefault("bone-meal-success-chance", 0.45));
|
||||
if (arguments.containsKey("bottom-block-tags")) {
|
||||
return new SaplingBlockBehavior(Key.of(feature), stageProperty, MiscUtils.getAsStringList(arguments.get("bottom-block-tags")).stream().map(it -> BlockTags.getOrCreate(Key.of(it))).toList(), boneMealSuccessChance);
|
||||
} else if (arguments.containsKey("tags")) {
|
||||
return new SaplingBlockBehavior(Key.of(feature), stageProperty, MiscUtils.getAsStringList(arguments.get("tags")).stream().map(it -> BlockTags.getOrCreate(Key.of(it))).toList(), boneMealSuccessChance);
|
||||
} else {
|
||||
return new SaplingBlockBehavior(Key.of(feature), stageProperty, List.of(DIRT_TAG, FARMLAND), boneMealSuccessChance);
|
||||
}
|
||||
Tuple<List<Object>, Set<Object>, Set<String>> tuple = readTagsAndState(arguments);
|
||||
return new SaplingBlockBehavior(Key.of(feature), stageProperty, tuple.left(), tuple.mid(), tuple.right(), boneMealSuccessChance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class SugarCaneBlockBehavior extends BushBlockBehavior {
|
||||
|
||||
public SugarCaneBlockBehavior(List<Object> tagsCanSurviveOn, Set<Object> blocksCansSurviveOn, Set<String> customBlocksCansSurviveOn) {
|
||||
super(tagsCanSurviveOn, blocksCansSurviveOn, customBlocksCansSurviveOn);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public class BukkitVanillaLootManager implements VanillaLootManager, Listener {
|
||||
VanillaLoot vanillaLoot = this.blockLoots.computeIfAbsent(BlockStateUtils.blockStateToId(blockState), k -> new VanillaLoot(VanillaLoot.Type.BLOCK));
|
||||
vanillaLoot.addLootTable(lootTable);
|
||||
} else {
|
||||
for (Object blockState : BlockStateUtils.getAllBlockStates(Key.of(target))) {
|
||||
for (Object blockState : BlockStateUtils.getAllVanillaBlockStates(Key.of(target))) {
|
||||
if (blockState == Reflections.instance$Blocks$AIR$defaultState) {
|
||||
this.plugin.logger().warn(path, "Failed to load " + id + ". Invalid target " + target);
|
||||
return;
|
||||
|
||||
@@ -6,7 +6,6 @@ import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.network.impl.*;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.core.block.BlockStateParser;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.PushReaction;
|
||||
import net.momirealms.craftengine.core.util.Instrument;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MapColor;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class BlockStateUtils {
|
||||
public static final IdentityHashMap<Object, Object> CLIENT_SIDE_NOTE_BLOCKS = new IdentityHashMap<>();
|
||||
@@ -27,8 +32,36 @@ public class BlockStateUtils {
|
||||
hasInit = true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Object> getAllBlockStates(String blockState) {
|
||||
int index = blockState.indexOf('[');
|
||||
if (index == -1) {
|
||||
return getAllBlockStates(Key.of(blockState));
|
||||
} else {
|
||||
String blockTypeString = blockState.substring(0, index);
|
||||
Key block = Key.of(blockTypeString);
|
||||
Optional<CustomBlock> optionalCustomBlock = BukkitBlockManager.instance().getBlock(block);
|
||||
if (optionalCustomBlock.isPresent()) {
|
||||
ImmutableBlockState state = BlockStateParser.deserialize(blockState);
|
||||
if (state == null) {
|
||||
return List.of();
|
||||
} else {
|
||||
return List.of(state.customBlockState().handle());
|
||||
}
|
||||
} else {
|
||||
BlockData blockData = Bukkit.createBlockData(blockState);
|
||||
return List.of(blockDataToBlockState(blockData));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Object> getAllBlockStates(Key block) {
|
||||
Optional<CustomBlock> optionalCustomBlock = BukkitBlockManager.instance().getBlock(block);
|
||||
return optionalCustomBlock.map(customBlock -> customBlock.variantProvider().states().stream().map(it -> it.customBlockState().handle()).toList())
|
||||
.orElseGet(() -> getAllVanillaBlockStates(block));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Object> getAllVanillaBlockStates(Key block) {
|
||||
try {
|
||||
Object blockIns = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$BLOCK, Reflections.method$ResourceLocation$fromNamespaceAndPath.invoke(null, block.namespace(), block.value()));
|
||||
Object definition = Reflections.field$Block$StateDefinition.get(blockIns);
|
||||
|
||||
@@ -3,8 +3,6 @@ package net.momirealms.craftengine.core.plugin.network;
|
||||
import io.netty.channel.Channel;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface NetworkManager {
|
||||
String MOD_CHANNEL = "craftengine:payload";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user