mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-21 16:09:26 +00:00
限制摆放
This commit is contained in:
@@ -10,7 +10,7 @@ public class BukkitFurnitureHitboxTypes extends FurnitureHitBoxTypes {
|
|||||||
static {
|
static {
|
||||||
register(INTERACTION, InteractionFurnitureHitboxConfig.FACTORY);
|
register(INTERACTION, InteractionFurnitureHitboxConfig.FACTORY);
|
||||||
register(SHULKER, ShulkerFurnitureHitboxConfig.FACTORY);
|
register(SHULKER, ShulkerFurnitureHitboxConfig.FACTORY);
|
||||||
register(CUSTOM, CustomFurnitureHitboxConfig.FACTORY);
|
register(CUSTOM, CustomFurnitureHitboxConfig.FACTORY);
|
||||||
if (VersionHelper.isOrAbove1_21_6()) {
|
if (VersionHelper.isOrAbove1_21_6()) {
|
||||||
register(HAPPY_GHAST, HappyGhastFurnitureHitboxConfig.FACTORY);
|
register(HAPPY_GHAST, HappyGhastFurnitureHitboxConfig.FACTORY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class InteractionFurnitureHitbox extends AbstractFurnitureHitBox {
|
|||||||
int interactionId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
int interactionId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet();
|
||||||
this.spawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of(
|
this.spawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of(
|
||||||
FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
|
||||||
interactionId, UUID.randomUUID(), position.x, position.y, position.z, 0, position.yRot,
|
interactionId, UUID.randomUUID(), pos.x, pos.y, pos.z, 0, position.yRot,
|
||||||
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
MEntityTypes.INTERACTION, 0, CoreReflections.instance$Vec3$Zero, 0
|
||||||
),
|
),
|
||||||
FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(interactionId, config.cachedValues())
|
FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(interactionId, config.cachedValues())
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
|||||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||||
import net.momirealms.craftengine.bukkit.util.EventUtils;
|
import net.momirealms.craftengine.bukkit.util.EventUtils;
|
||||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig;
|
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureDataAccessor;
|
|
||||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureVariant;
|
|
||||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
|
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
|
||||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
@@ -26,10 +24,8 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
|||||||
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
import net.momirealms.craftengine.core.plugin.context.event.EventTrigger;
|
||||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.util.Cancellable;
|
import net.momirealms.craftengine.core.plugin.logger.Debugger;
|
||||||
import net.momirealms.craftengine.core.util.ItemUtils;
|
import net.momirealms.craftengine.core.util.*;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
|
||||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
|
||||||
import net.momirealms.craftengine.core.world.Vec3d;
|
import net.momirealms.craftengine.core.world.Vec3d;
|
||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||||
@@ -38,17 +34,17 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class FurnitureItemBehavior extends ItemBehavior {
|
public class FurnitureItemBehavior extends ItemBehavior {
|
||||||
public static final Factory FACTORY = new Factory();
|
public static final Factory FACTORY = new Factory();
|
||||||
|
private static final Set<String> ALLOWED_ANCHOR_TYPES = Set.of("wall", "ceiling", "ground");
|
||||||
private final Key id;
|
private final Key id;
|
||||||
|
private final Map<AnchorType, Rule> rules;
|
||||||
|
|
||||||
public FurnitureItemBehavior(Key id) {
|
public FurnitureItemBehavior(Key id, Map<AnchorType, Rule> rules) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.rules = rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Key furnitureId() {
|
public Key furnitureId() {
|
||||||
@@ -67,12 +63,24 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
|||||||
return InteractionResult.FAIL;
|
return InteractionResult.FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Direction clickedFace = context.getClickedFace();
|
||||||
|
AnchorType anchorType = switch (clickedFace) {
|
||||||
|
case EAST, WEST, NORTH, SOUTH -> AnchorType.WALL;
|
||||||
|
case UP -> AnchorType.GROUND;
|
||||||
|
case DOWN -> AnchorType.CEILING;
|
||||||
|
};
|
||||||
|
|
||||||
FurnitureConfig customFurniture = optionalCustomFurniture.get();
|
FurnitureConfig customFurniture = optionalCustomFurniture.get();
|
||||||
FurnitureVariant variant = customFurniture.anyVariant();
|
FurnitureVariant variant = customFurniture.getVariant(anchorType.variantName());
|
||||||
if (variant == null) {
|
if (variant == null) {
|
||||||
return InteractionResult.FAIL;
|
return InteractionResult.FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rule rule = this.rules.get(anchorType);
|
||||||
|
if (rule == null) {
|
||||||
|
rule = Rule.DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
Player player = context.getPlayer();
|
Player player = context.getPlayer();
|
||||||
if (player != null && player.isAdventureMode()) {
|
if (player != null && player.isAdventureMode()) {
|
||||||
return InteractionResult.FAIL;
|
return InteractionResult.FAIL;
|
||||||
@@ -80,14 +88,27 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
|||||||
|
|
||||||
Vec3d clickedPosition = context.getClickLocation();
|
Vec3d clickedPosition = context.getClickLocation();
|
||||||
|
|
||||||
|
// get position and rotation for placement
|
||||||
|
Vec3d finalPlacePosition;
|
||||||
|
double furnitureYaw;
|
||||||
|
if (anchorType == AnchorType.WALL) {
|
||||||
|
furnitureYaw = Direction.getYaw(clickedFace);
|
||||||
|
if (clickedFace == Direction.EAST || clickedFace == Direction.WEST) {
|
||||||
|
Pair<Double, Double> xz = rule.alignmentRule().apply(Pair.of(clickedPosition.y(), clickedPosition.z()));
|
||||||
|
finalPlacePosition = new Vec3d(clickedPosition.x(), xz.left(), xz.right());
|
||||||
|
} else {
|
||||||
|
Pair<Double, Double> xz = rule.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.y()));
|
||||||
|
finalPlacePosition = new Vec3d(xz.left(), xz.right(), clickedPosition.z());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
furnitureYaw = rule.rotationRule().apply(180 + (player != null ? player.yRot() : 0));
|
||||||
|
Pair<Double, Double> xz = rule.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.z()));
|
||||||
|
finalPlacePosition = new Vec3d(xz.left(), clickedPosition.y(), xz.right());
|
||||||
|
}
|
||||||
|
|
||||||
// trigger event
|
// trigger event
|
||||||
org.bukkit.entity.Player bukkitPlayer = player != null ? (org.bukkit.entity.Player) player.platformPlayer() : null;
|
org.bukkit.entity.Player bukkitPlayer = player != null ? (org.bukkit.entity.Player) player.platformPlayer() : null;
|
||||||
World world = (World) context.getLevel().platformWorld();
|
World world = (World) context.getLevel().platformWorld();
|
||||||
|
|
||||||
// get position and rotation for placement
|
|
||||||
Vec3d finalPlacePosition = clickedPosition;
|
|
||||||
double furnitureYaw = 180 + (player != null ? player.yRot() : 0);
|
|
||||||
|
|
||||||
Location furnitureLocation = new Location(world, finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, 0);
|
Location furnitureLocation = new Location(world, finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, 0);
|
||||||
WorldPosition furniturePos = LocationUtils.toWorldPosition(furnitureLocation);
|
WorldPosition furniturePos = LocationUtils.toWorldPosition(furnitureLocation);
|
||||||
List<AABB> aabbs = new ArrayList<>();
|
List<AABB> aabbs = new ArrayList<>();
|
||||||
@@ -162,17 +183,59 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
|||||||
if (id == null) {
|
if (id == null) {
|
||||||
throw new LocalizedResourceConfigException("warning.config.item.behavior.furniture.missing_furniture", new IllegalArgumentException("Missing required parameter 'furniture' for furniture_item behavior"));
|
throw new LocalizedResourceConfigException("warning.config.item.behavior.furniture.missing_furniture", new IllegalArgumentException("Missing required parameter 'furniture' for furniture_item behavior"));
|
||||||
}
|
}
|
||||||
|
Map<String, Object> rulesMap = ResourceConfigUtils.getAsMapOrNull(arguments.get("rules"), "rules");
|
||||||
|
Key furnitureId;
|
||||||
if (id instanceof Map<?,?> map) {
|
if (id instanceof Map<?,?> map) {
|
||||||
|
Map<String, Object> furnitureSection;
|
||||||
if (map.containsKey(key.toString())) {
|
if (map.containsKey(key.toString())) {
|
||||||
// 防呆
|
// 防呆
|
||||||
BukkitFurnitureManager.instance().parser().addPendingConfigSection(new PendingConfigSection(pack, path, node, key, MiscUtils.castToMap(map.get(key.toString()), false)));
|
furnitureSection = MiscUtils.castToMap(map.get(key.toString()), false);
|
||||||
|
BukkitFurnitureManager.instance().parser().addPendingConfigSection(new PendingConfigSection(pack, path, node, key, furnitureSection));
|
||||||
} else {
|
} else {
|
||||||
BukkitFurnitureManager.instance().parser().addPendingConfigSection(new PendingConfigSection(pack, path, node, key, MiscUtils.castToMap(map, false)));
|
furnitureSection = MiscUtils.castToMap(map, false);
|
||||||
|
BukkitFurnitureManager.instance().parser().addPendingConfigSection(new PendingConfigSection(pack, path, node, key, furnitureSection));
|
||||||
|
}
|
||||||
|
furnitureId = key;
|
||||||
|
// 兼容老版本
|
||||||
|
if (rulesMap == null) {
|
||||||
|
Map<String, Object> placementSection = ResourceConfigUtils.getAsMapOrNull(furnitureSection.get("placement"), "placement");
|
||||||
|
if (placementSection != null) {
|
||||||
|
rulesMap = new HashMap<>();
|
||||||
|
for (Map.Entry<String, Object> entry : placementSection.entrySet()) {
|
||||||
|
if (entry.getValue() instanceof Map<?, ?> innerMap) {
|
||||||
|
if (innerMap.containsKey("rules")) {
|
||||||
|
Map<String, Object> rules = ResourceConfigUtils.getAsMap(innerMap.get("rules"), "rules");
|
||||||
|
if (ALLOWED_ANCHOR_TYPES.contains(entry.getKey())) {
|
||||||
|
rulesMap.put(entry.getKey(), rules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new FurnitureItemBehavior(key);
|
|
||||||
} else {
|
} else {
|
||||||
return new FurnitureItemBehavior(Key.of(id.toString()));
|
furnitureId = Key.of(id.toString());
|
||||||
}
|
}
|
||||||
|
Map<AnchorType, Rule> rules = new EnumMap<>(AnchorType.class);
|
||||||
|
if (rulesMap != null) {
|
||||||
|
for (Map.Entry<String, Object> entry : rulesMap.entrySet()) {
|
||||||
|
try {
|
||||||
|
AnchorType type = AnchorType.valueOf(entry.getKey().toUpperCase(Locale.ROOT));
|
||||||
|
Map<String, Object> ruleSection = MiscUtils.castToMap(entry.getValue(), true);
|
||||||
|
rules.put(type, new Rule(
|
||||||
|
ResourceConfigUtils.getAsEnum(ruleSection.get("alignment"), AlignmentRule.class, AlignmentRule.ANY),
|
||||||
|
ResourceConfigUtils.getAsEnum(ruleSection.get("rotation"), RotationRule.class, RotationRule.ANY)
|
||||||
|
));
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
Debugger.FURNITURE.debug(() -> "Invalid anchor type: " + entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new FurnitureItemBehavior(furnitureId, rules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record Rule(AlignmentRule alignmentRule, RotationRule rotationRule) {
|
||||||
|
public static final Rule DEFAULT = new Rule(AlignmentRule.ANY, RotationRule.ANY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ items:
|
|||||||
model: minecraft:item/custom/bench
|
model: minecraft:item/custom/bench
|
||||||
behavior:
|
behavior:
|
||||||
type: furniture_item
|
type: furniture_item
|
||||||
|
rules:
|
||||||
|
ground:
|
||||||
|
rotation: four
|
||||||
|
alignment: center
|
||||||
furniture:
|
furniture:
|
||||||
settings:
|
settings:
|
||||||
item: default:bench
|
item: default:bench
|
||||||
@@ -17,8 +21,8 @@ items:
|
|||||||
loot-spawn-offset: 0.5,0.5,0
|
loot-spawn-offset: 0.5,0.5,0
|
||||||
elements:
|
elements:
|
||||||
- item: default:bench
|
- item: default:bench
|
||||||
display-transform: NONE
|
display-transform: none
|
||||||
billboard: FIXED
|
billboard: fixed
|
||||||
position: 0.5,0,0
|
position: 0.5,0,0
|
||||||
translation: 0,0.5,0
|
translation: 0,0.5,0
|
||||||
shadow-radius: 1
|
shadow-radius: 1
|
||||||
|
|||||||
@@ -7,6 +7,16 @@ items:
|
|||||||
behavior:
|
behavior:
|
||||||
type: furniture_item
|
type: furniture_item
|
||||||
furniture: default:flower_basket
|
furniture: default:flower_basket
|
||||||
|
rules:
|
||||||
|
ground:
|
||||||
|
rotation: any
|
||||||
|
alignment: any
|
||||||
|
wall:
|
||||||
|
rotation: any
|
||||||
|
alignment: any
|
||||||
|
ceiling:
|
||||||
|
rotation: any
|
||||||
|
alignment: any
|
||||||
default:flower_basket_ground:
|
default:flower_basket_ground:
|
||||||
material: nether_brick
|
material: nether_brick
|
||||||
model: minecraft:item/custom/flower_basket_ground
|
model: minecraft:item/custom/flower_basket_ground
|
||||||
@@ -27,15 +37,12 @@ furniture:
|
|||||||
template: default:loot_table/furniture
|
template: default:loot_table/furniture
|
||||||
arguments:
|
arguments:
|
||||||
item: default:flower_basket
|
item: default:flower_basket
|
||||||
placement:
|
variants:
|
||||||
ground:
|
ground:
|
||||||
rules:
|
|
||||||
rotation: ANY
|
|
||||||
alignment: ANY
|
|
||||||
elements:
|
elements:
|
||||||
- item: default:flower_basket_ground
|
- item: default:flower_basket_ground
|
||||||
display-transform: NONE
|
display-transform: none
|
||||||
billboard: FIXED
|
billboard: fixed
|
||||||
position: 0,0,0
|
position: 0,0,0
|
||||||
translation: 0,0.5,0
|
translation: 0,0.5,0
|
||||||
shadow-radius: 0.5
|
shadow-radius: 0.5
|
||||||
@@ -50,12 +57,10 @@ furniture:
|
|||||||
height: 0.5
|
height: 0.5
|
||||||
interactive: true
|
interactive: true
|
||||||
wall:
|
wall:
|
||||||
rules:
|
|
||||||
alignment: ANY
|
|
||||||
elements:
|
elements:
|
||||||
- item: default:flower_basket_wall
|
- item: default:flower_basket_wall
|
||||||
display-transform: NONE
|
display-transform: none
|
||||||
billboard: FIXED
|
billboard: fixed
|
||||||
position: 0,0,0.2
|
position: 0,0,0.2
|
||||||
translation: 0,0,0
|
translation: 0,0,0
|
||||||
hitboxes:
|
hitboxes:
|
||||||
@@ -76,13 +81,10 @@ furniture:
|
|||||||
height: 0.75
|
height: 0.75
|
||||||
interactive: true
|
interactive: true
|
||||||
ceiling:
|
ceiling:
|
||||||
rules:
|
|
||||||
rotation: ANY
|
|
||||||
alignment: ANY
|
|
||||||
elements:
|
elements:
|
||||||
- item: default:flower_basket_ceiling
|
- item: default:flower_basket_ceiling
|
||||||
display-transform: NONE
|
display-transform: none
|
||||||
billboard: FIXED
|
billboard: fixed
|
||||||
position: 0,-0.46,0
|
position: 0,-0.46,0
|
||||||
translation: 0,0,0
|
translation: 0,0,0
|
||||||
hitboxes:
|
hitboxes:
|
||||||
|
|||||||
@@ -6,18 +6,19 @@ items:
|
|||||||
model: minecraft:item/custom/wooden_chair
|
model: minecraft:item/custom/wooden_chair
|
||||||
behavior:
|
behavior:
|
||||||
type: furniture_item
|
type: furniture_item
|
||||||
|
rules:
|
||||||
|
ground:
|
||||||
|
rotation: any
|
||||||
|
alignment: any
|
||||||
furniture:
|
furniture:
|
||||||
settings:
|
settings:
|
||||||
item: default:wooden_chair
|
item: default:wooden_chair
|
||||||
sounds:
|
sounds:
|
||||||
break: minecraft:block.bamboo_wood.break
|
break: minecraft:block.bamboo_wood.break
|
||||||
place: minecraft:block.bamboo_wood.place
|
place: minecraft:block.bamboo_wood.place
|
||||||
placement:
|
variants:
|
||||||
ground:
|
ground:
|
||||||
loot-spawn-offset: 0,0.4,0
|
loot-spawn-offset: 0,0.4,0
|
||||||
rules:
|
|
||||||
rotation: ANY
|
|
||||||
alignment: ANY
|
|
||||||
elements:
|
elements:
|
||||||
- item: default:wooden_chair
|
- item: default:wooden_chair
|
||||||
display-transform: NONE
|
display-transform: NONE
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture;
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
@Deprecated(since = "0.0.66")
|
|
||||||
public enum AnchorType {
|
public enum AnchorType {
|
||||||
GROUND(0),
|
GROUND(0, "ground"),
|
||||||
WALL(1),
|
WALL(1, "wall"),
|
||||||
CEILING(2);
|
CEILING(2, "ceiling");
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
|
private final String variantName;
|
||||||
|
|
||||||
AnchorType(int id) {
|
AnchorType(int id, String variantName) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.variantName = variantName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String variantName() {
|
||||||
|
return variantName;
|
||||||
|
}
|
||||||
|
|
||||||
public static AnchorType byId(int id) {
|
public static AnchorType byId(int id) {
|
||||||
return values()[id];
|
return values()[id];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public final class ResourceConfigUtils {
|
|||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return Enum.valueOf(clazz, o.toString().toUpperCase(Locale.ENGLISH));
|
return Enum.valueOf(clazz, o.toString().toUpperCase(Locale.ROOT));
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user