mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-03 22:26:16 +00:00
Add furniture spawn, remove, and replace functions
Introduces SpawnFurnitureFunction, RemoveFurnitureFunction, and ReplaceFurnitureFunction for event contexts, enabling dynamic furniture manipulation via context functions. Adds BlockStateHitBox type and registration, with cleanup logic in BukkitFurniture. Updates parameter providers and function registries to support new features.
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
@@ -8,14 +11,12 @@ import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class HitBoxTypes {
|
||||
public static final Key INTERACTION = Key.of("minecraft:interaction");
|
||||
public static final Key SHULKER = Key.of("minecraft:shulker");
|
||||
public static final Key HAPPY_GHAST = Key.of("minecraft:happy_ghast");
|
||||
public static final Key CUSTOM = Key.of("minecraft:custom");
|
||||
public static final Key BLOCKSTATE = Key.of("minecraft:blockstate");
|
||||
|
||||
public static void register(Key key, HitBoxFactory factory) {
|
||||
Holder.Reference<HitBoxFactory> holder = ((WritableRegistry<HitBoxFactory>) BuiltInRegistries.HITBOX_FACTORY)
|
||||
|
||||
@@ -1,7 +1,40 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.*;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.ActionBarFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.BreakBlockFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.CancelEventFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.CommandFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.CommonFunctions;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.DropLootFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.Function;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.LevelerExpFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.MessageFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.OpenWindowFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.ParticleFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.PlaceBlockFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.PlaySoundFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.PotionEffectFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.RemoveCooldownFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.RemoveFurnitureFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.RemovePotionEffectFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.ReplaceFurnitureFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.RunFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.SetCooldownFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.SetCountFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.SetFoodFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.SetSaturationFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.SpawnFurnitureFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.SwingHandFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.TitleFunction;
|
||||
import net.momirealms.craftengine.core.plugin.context.function.UpdateInteractionFunction;
|
||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
@@ -12,8 +45,6 @@ import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class EventFunctions {
|
||||
|
||||
static {
|
||||
@@ -39,6 +70,9 @@ public class EventFunctions {
|
||||
register(CommonFunctions.LEVELER_EXP, new LevelerExpFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.SET_COOLDOWN, new SetCooldownFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.REMOVE_COOLDOWN, new RemoveCooldownFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.SPAWN_FURNITURE, new SpawnFurnitureFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.REMOVE_FURNITURE, new RemoveFurnitureFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
register(CommonFunctions.REPLACE_FURNITURE, new ReplaceFurnitureFunction.FactoryImpl<>(EventConditions::fromMap));
|
||||
}
|
||||
|
||||
public static void register(Key key, FunctionFactory<PlayerOptionalContext> factory) {
|
||||
|
||||
@@ -27,4 +27,7 @@ public final class CommonFunctions {
|
||||
public static final Key DROP_LOOT = Key.of("craftengine:drop_loot");
|
||||
public static final Key SWING_HAND = Key.of("craftengine:swing_hand");
|
||||
public static final Key LEVELER_EXP = Key.of("craftengine:leveler_exp");
|
||||
public static final Key SPAWN_FURNITURE = Key.of("craftengine:spawn_furniture");
|
||||
public static final Key REMOVE_FURNITURE = Key.of("craftengine:remove_furniture");
|
||||
public static final Key REPLACE_FURNITURE = Key.of("craftengine:replace_furniture");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.function;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
|
||||
public class RemoveFurnitureFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
||||
private final boolean dropLoot;
|
||||
private final boolean playSound;
|
||||
|
||||
public RemoveFurnitureFunction(boolean dropLoot, boolean playSound, List<Condition<CTX>> predicates) {
|
||||
super(predicates);
|
||||
this.dropLoot = dropLoot;
|
||||
this.playSound = playSound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runInternal(CTX ctx) {
|
||||
Optional<WorldPosition> optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION);
|
||||
if (optionalWorldPosition.isPresent()) {
|
||||
// Buscar muebles en el contexto
|
||||
Optional<Furniture> optionalFurniture = ctx.getOptionalParameter(DirectContextParameters.FURNITURE);
|
||||
if (optionalFurniture.isPresent()) {
|
||||
Furniture furniture = optionalFurniture.get();
|
||||
if (furniture.isValid()) {
|
||||
furniture.destroy();
|
||||
// TODO: Implementar lógica para dropear loot y reproducir sonidos
|
||||
// usando this.dropLoot y this.playSound cuando sea necesario
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return CommonFunctions.REMOVE_FURNITURE;
|
||||
}
|
||||
|
||||
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
|
||||
|
||||
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<CTX> create(Map<String, Object> arguments) {
|
||||
boolean dropLoot = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("drop-loot", true), "drop-loot");
|
||||
boolean playSound = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("play-sound", true), "play-sound");
|
||||
return new RemoveFurnitureFunction<>(dropLoot, playSound, getPredicates(arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.function;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
|
||||
public class ReplaceFurnitureFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
||||
private final Key newFurnitureId;
|
||||
private final NumberProvider x;
|
||||
private final NumberProvider y;
|
||||
private final NumberProvider z;
|
||||
private final NumberProvider pitch;
|
||||
private final NumberProvider yaw;
|
||||
private final AnchorType anchorType;
|
||||
private final boolean dropLoot;
|
||||
private final boolean playSound;
|
||||
|
||||
public ReplaceFurnitureFunction(Key newFurnitureId, NumberProvider x, NumberProvider y, NumberProvider z,
|
||||
NumberProvider pitch, NumberProvider yaw, AnchorType anchorType,
|
||||
boolean dropLoot, boolean playSound, List<Condition<CTX>> predicates) {
|
||||
super(predicates);
|
||||
this.newFurnitureId = newFurnitureId;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.pitch = pitch;
|
||||
this.yaw = yaw;
|
||||
this.anchorType = anchorType;
|
||||
this.dropLoot = dropLoot;
|
||||
this.playSound = playSound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runInternal(CTX ctx) {
|
||||
Optional<WorldPosition> optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION);
|
||||
Optional<Furniture> optionalOldFurniture = ctx.getOptionalParameter(DirectContextParameters.FURNITURE);
|
||||
|
||||
if (optionalWorldPosition.isPresent() && optionalOldFurniture.isPresent()) {
|
||||
Furniture oldFurniture = optionalOldFurniture.get();
|
||||
|
||||
// Obtener la nueva posición o usar la actual del mueble
|
||||
double xPos = this.x.getDouble(ctx);
|
||||
double yPos = this.y.getDouble(ctx);
|
||||
double zPos = this.z.getDouble(ctx);
|
||||
float pitchValue = this.pitch.getFloat(ctx);
|
||||
float yawValue = this.yaw.getFloat(ctx);
|
||||
|
||||
WorldPosition newPosition = new WorldPosition(optionalWorldPosition.get().world(), xPos, yPos, zPos, pitchValue, yawValue);
|
||||
|
||||
// Obtener el nuevo mueble
|
||||
Optional<CustomFurniture> optionalNewFurniture = CraftEngine.instance().furnitureManager().furnitureById(this.newFurnitureId);
|
||||
if (optionalNewFurniture.isPresent()) {
|
||||
CustomFurniture newFurniture = optionalNewFurniture.get();
|
||||
AnchorType anchor = this.anchorType != null ? this.anchorType : newFurniture.getAnyAnchorType();
|
||||
|
||||
// Remover el mueble antiguo
|
||||
if (oldFurniture.isValid()) {
|
||||
oldFurniture.destroy();
|
||||
// TODO: Implementar lógica para dropear loot usando this.dropLoot
|
||||
}
|
||||
|
||||
// Colocar el nuevo mueble
|
||||
FurnitureExtraData extraData = FurnitureExtraData.builder().anchorType(anchor).build();
|
||||
CraftEngine.instance().furnitureManager().place(newPosition, newFurniture, extraData, this.playSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return CommonFunctions.REPLACE_FURNITURE;
|
||||
}
|
||||
|
||||
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
|
||||
|
||||
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<CTX> create(Map<String, Object> arguments) {
|
||||
String furnitureIdStr = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("furniture-id"), "warning.config.function.replace_furniture.missing_furniture_id");
|
||||
Key furnitureId = Key.of(furnitureIdStr);
|
||||
NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "<arg:position.x>"));
|
||||
NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "<arg:position.y>"));
|
||||
NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "<arg:position.z>"));
|
||||
NumberProvider pitch = NumberProviders.fromObject(arguments.getOrDefault("pitch", "<arg:pitch>"));
|
||||
NumberProvider yaw = NumberProviders.fromObject(arguments.getOrDefault("yaw", "<arg:yaw>"));
|
||||
AnchorType anchorType = Optional.ofNullable(arguments.get("anchor-type")).map(o -> AnchorType.valueOf(o.toString().toUpperCase())).orElse(null);
|
||||
boolean dropLoot = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("drop-loot", true), "drop-loot");
|
||||
boolean playSound = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("play-sound", true), "play-sound");
|
||||
return new ReplaceFurnitureFunction<>(furnitureId, x, y, z, pitch, yaw, anchorType, dropLoot, playSound, getPredicates(arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.function;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
|
||||
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
|
||||
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.context.Condition;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.number.NumberProviders;
|
||||
import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||
|
||||
public class SpawnFurnitureFunction<CTX extends Context> extends AbstractConditionalFunction<CTX> {
|
||||
private final Key furnitureId;
|
||||
private final NumberProvider x;
|
||||
private final NumberProvider y;
|
||||
private final NumberProvider z;
|
||||
private final NumberProvider pitch;
|
||||
private final NumberProvider yaw;
|
||||
private final AnchorType anchorType;
|
||||
private final boolean playSound;
|
||||
|
||||
public SpawnFurnitureFunction(Key furnitureId, NumberProvider x, NumberProvider y, NumberProvider z,
|
||||
NumberProvider pitch, NumberProvider yaw, AnchorType anchorType,
|
||||
boolean playSound, List<Condition<CTX>> predicates) {
|
||||
super(predicates);
|
||||
this.furnitureId = furnitureId;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.pitch = pitch;
|
||||
this.yaw = yaw;
|
||||
this.anchorType = anchorType;
|
||||
this.playSound = playSound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runInternal(CTX ctx) {
|
||||
Optional<WorldPosition> optionalWorldPosition = ctx.getOptionalParameter(DirectContextParameters.POSITION);
|
||||
if (optionalWorldPosition.isPresent()) {
|
||||
World world = optionalWorldPosition.get().world();
|
||||
double xPos = this.x.getDouble(ctx);
|
||||
double yPos = this.y.getDouble(ctx);
|
||||
double zPos = this.z.getDouble(ctx);
|
||||
float pitchValue = this.pitch.getFloat(ctx);
|
||||
float yawValue = this.yaw.getFloat(ctx);
|
||||
|
||||
WorldPosition position = new WorldPosition(world, xPos, yPos, zPos, pitchValue, yawValue);
|
||||
|
||||
Optional<CustomFurniture> optionalFurniture = CraftEngine.instance().furnitureManager().furnitureById(this.furnitureId);
|
||||
if (optionalFurniture.isPresent()) {
|
||||
CustomFurniture furniture = optionalFurniture.get();
|
||||
AnchorType anchor = this.anchorType != null ? this.anchorType : furniture.getAnyAnchorType();
|
||||
FurnitureExtraData extraData = FurnitureExtraData.builder().anchorType(anchor).build();
|
||||
CraftEngine.instance().furnitureManager().place(position, furniture, extraData, this.playSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return CommonFunctions.SPAWN_FURNITURE;
|
||||
}
|
||||
|
||||
public static class FactoryImpl<CTX extends Context> extends AbstractFactory<CTX> {
|
||||
|
||||
public FactoryImpl(java.util.function.Function<Map<String, Object>, Condition<CTX>> factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<CTX> create(Map<String, Object> arguments) {
|
||||
String furnitureIdStr = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("furniture-id"), "warning.config.function.spawn_furniture.missing_furniture_id");
|
||||
Key furnitureId = Key.of(furnitureIdStr);
|
||||
NumberProvider x = NumberProviders.fromObject(arguments.getOrDefault("x", "<arg:position.x>"));
|
||||
NumberProvider y = NumberProviders.fromObject(arguments.getOrDefault("y", "<arg:position.y>"));
|
||||
NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "<arg:position.z>"));
|
||||
NumberProvider pitch = NumberProviders.fromObject(arguments.getOrDefault("pitch", "<arg:pitch>"));
|
||||
NumberProvider yaw = NumberProviders.fromObject(arguments.getOrDefault("yaw", "<arg:yaw>"));
|
||||
AnchorType anchorType = Optional.ofNullable(arguments.get("anchor-type")).map(o -> AnchorType.valueOf(o.toString().toUpperCase())).orElse(null);
|
||||
boolean playSound = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("play-sound", true), "play-sound");
|
||||
return new SpawnFurnitureFunction<>(furnitureId, x, y, z, pitch, yaw, anchorType, playSound, getPredicates(arguments));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,25 @@
|
||||
package net.momirealms.craftengine.core.plugin.context.parameter;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.plugin.context.ChainParameterProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextKey;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||
import net.momirealms.craftengine.core.plugin.context.ChainParameterProvider;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextKey;
|
||||
|
||||
public class FurnitureParameterProvider implements ChainParameterProvider<Furniture> {
|
||||
private static final Map<ContextKey<?>, Function<Furniture, Object>> CONTEXT_FUNCTIONS = new HashMap<>();
|
||||
static {
|
||||
CONTEXT_FUNCTIONS.put(DirectContextParameters.ID, Furniture::id);
|
||||
CONTEXT_FUNCTIONS.put(DirectContextParameters.UUID, Furniture::uuid);
|
||||
CONTEXT_FUNCTIONS.put(DirectContextParameters.ANCHOR_TYPE, Furniture::anchorType);
|
||||
CONTEXT_FUNCTIONS.put(DirectContextParameters.X, furniture -> furniture.position().x());
|
||||
CONTEXT_FUNCTIONS.put(DirectContextParameters.Y, furniture -> furniture.position().y());
|
||||
CONTEXT_FUNCTIONS.put(DirectContextParameters.Z, furniture -> furniture.position().z());
|
||||
CONTEXT_FUNCTIONS.put(DirectContextParameters.PITCH, furniture -> furniture.position().yRot());
|
||||
CONTEXT_FUNCTIONS.put(DirectContextParameters.YAW, furniture -> furniture.position().xRot());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
Reference in New Issue
Block a user