mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-28 03:19:14 +00:00
refactor furniture
This commit is contained in:
@@ -34,7 +34,7 @@ public class CraftEngineFurniture {
|
||||
* @return the custom furniture
|
||||
*/
|
||||
public static CustomFurniture byId(@NotNull Key id) {
|
||||
return BukkitFurnitureManager.instance().getFurniture(id).orElse(null);
|
||||
return BukkitFurnitureManager.instance().furnitureById(id).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +139,7 @@ public class CraftEngineFurniture {
|
||||
*/
|
||||
@Nullable
|
||||
public static LoadedFurniture getLoadedFurnitureByBaseEntity(@NotNull Entity baseEntity) {
|
||||
return BukkitFurnitureManager.instance().getLoadedFurnitureByRealEntityId(baseEntity.getEntityId());
|
||||
return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntity.getEntityId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,7 +152,7 @@ public class CraftEngineFurniture {
|
||||
public static LoadedFurniture getLoadedFurnitureBySeat(@NotNull Entity seat) {
|
||||
Integer baseEntityId = seat.getPersistentDataContainer().get(BukkitFurnitureManager.FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
|
||||
if (baseEntityId == null) return null;
|
||||
return BukkitFurnitureManager.instance().getLoadedFurnitureByRealEntityId(baseEntityId);
|
||||
return BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(baseEntityId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +163,7 @@ public class CraftEngineFurniture {
|
||||
*/
|
||||
public static boolean remove(@NotNull Entity furniture) {
|
||||
if (!isFurniture(furniture)) return false;
|
||||
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().getLoadedFurnitureByRealEntityId(furniture.getEntityId());
|
||||
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId());
|
||||
if (loadedFurniture == null) return false;
|
||||
loadedFurniture.destroy();
|
||||
return true;
|
||||
@@ -181,7 +181,7 @@ public class CraftEngineFurniture {
|
||||
boolean dropLoot,
|
||||
boolean playSound) {
|
||||
if (!isFurniture(furniture)) return false;
|
||||
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().getLoadedFurnitureByRealEntityId(furniture.getEntityId());
|
||||
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId());
|
||||
if (loadedFurniture == null) return false;
|
||||
remove(loadedFurniture, (net.momirealms.craftengine.core.entity.player.Player) null, dropLoot, playSound);
|
||||
return true;
|
||||
@@ -201,7 +201,7 @@ public class CraftEngineFurniture {
|
||||
boolean dropLoot,
|
||||
boolean playSound) {
|
||||
if (!isFurniture(furniture)) return false;
|
||||
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().getLoadedFurnitureByRealEntityId(furniture.getEntityId());
|
||||
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(furniture.getEntityId());
|
||||
if (loadedFurniture == null) return false;
|
||||
remove(loadedFurniture, player, dropLoot, playSound);
|
||||
return true;
|
||||
|
||||
@@ -10,13 +10,15 @@ import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.loot.LootTable;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.HandlerList;
|
||||
@@ -31,35 +33,35 @@ import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class BukkitFurnitureManager implements FurnitureManager {
|
||||
public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
||||
public static final NamespacedKey FURNITURE_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_id"));
|
||||
public static final NamespacedKey FURNITURE_ANCHOR_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:anchor_type"));
|
||||
public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_to_base_entity"));
|
||||
public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_vector"));
|
||||
private static BukkitFurnitureManager instance;
|
||||
private final BukkitCraftEngine plugin;
|
||||
|
||||
private final Map<Key, CustomFurniture> byId = new HashMap<>();
|
||||
|
||||
private final FurnitureParser furnitureParser;
|
||||
private final Map<Integer, LoadedFurniture> furnitureByRealEntityId = new ConcurrentHashMap<>(256, 0.5f);
|
||||
private final Map<Integer, LoadedFurniture> furnitureByEntityId = new ConcurrentHashMap<>(512, 0.5f);
|
||||
// Event listeners
|
||||
private final Listener dismountListener;
|
||||
private final FurnitureEventListener furnitureEventListener;
|
||||
// tick task
|
||||
private SchedulerTask tickTask;
|
||||
// Cached command suggestions
|
||||
private final List<Suggestion> cachedSuggestions = new ArrayList<>();
|
||||
|
||||
public static BukkitFurnitureManager instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public BukkitFurnitureManager(BukkitCraftEngine plugin) {
|
||||
instance = this;
|
||||
this.plugin = plugin;
|
||||
this.furnitureParser = new FurnitureParser();
|
||||
this.furnitureEventListener = new FurnitureEventListener(this);
|
||||
this.dismountListener = VersionHelper.isVersionNewerThan1_20_3() ? new DismountListener1_20_3(this) : new DismountListener1_20(this::handleDismount);
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Furniture place(CustomFurniture furniture, Vec3d vec3d, net.momirealms.craftengine.core.world.World world, AnchorType anchorType, boolean playSound) {
|
||||
return this.place(furniture, new Location((World) world.platformWorld(), vec3d.x(), vec3d.y(), vec3d.z()), anchorType, playSound);
|
||||
}
|
||||
|
||||
public LoadedFurniture place(CustomFurniture furniture, Location location, AnchorType anchorType, boolean playSound) {
|
||||
@@ -77,151 +79,131 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
SoundData data = furniture.settings().sounds().placeSound();
|
||||
location.getWorld().playSound(location, data.id().toString(), SoundCategory.BLOCKS, data.volume(), data.pitch());
|
||||
}
|
||||
return getLoadedFurnitureByRealEntityId(furnitureEntity.getEntityId());
|
||||
return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delayedLoad() {
|
||||
this.initSuggestions();
|
||||
public ConfigSectionParser parser() {
|
||||
return this.furnitureParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSuggestions() {
|
||||
this.cachedSuggestions.clear();
|
||||
for (Key key : this.byId.keySet()) {
|
||||
this.cachedSuggestions.add(Suggestion.suggestion(key.toString()));
|
||||
}
|
||||
}
|
||||
public class FurnitureParser implements ConfigSectionParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[] { "furniture" };
|
||||
|
||||
@Override
|
||||
public Collection<Suggestion> cachedSuggestions() {
|
||||
return Collections.unmodifiableCollection(this.cachedSuggestions);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
Map<String, Object> lootMap = MiscUtils.castToMap(section.get("loot"), true);
|
||||
Map<String, Object> settingsMap = MiscUtils.castToMap(section.get("settings"), true);
|
||||
Map<String, Object> placementMap = MiscUtils.castToMap(section.get("placement"), true);
|
||||
EnumMap<AnchorType, CustomFurniture.Placement> placements = new EnumMap<>(AnchorType.class);
|
||||
if (placementMap == null) {
|
||||
throw new IllegalArgumentException("Missing required parameter 'placement' for furniture " + id);
|
||||
@Override
|
||||
public String[] sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Object> entry : placementMap.entrySet()) {
|
||||
// anchor type
|
||||
AnchorType anchorType = AnchorType.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH));
|
||||
Map<String, Object> placementArguments = MiscUtils.castToMap(entry.getValue(), true);
|
||||
@Override
|
||||
public int loadingSequence() {
|
||||
return LoadingSequence.FURNITURE;
|
||||
}
|
||||
|
||||
// furniture display elements
|
||||
List<FurnitureElement> elements = new ArrayList<>();
|
||||
List<Map<String, Object>> elementConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("elements", List.of());
|
||||
for (Map<String, Object> element : elementConfigs) {
|
||||
String key = (String) element.get("item");
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("Missing required parameter 'item' for furniture " + id);
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void parseSection(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
Map<String, Object> lootMap = MiscUtils.castToMap(section.get("loot"), true);
|
||||
Map<String, Object> settingsMap = MiscUtils.castToMap(section.get("settings"), true);
|
||||
Map<String, Object> placementMap = MiscUtils.castToMap(section.get("placement"), true);
|
||||
EnumMap<AnchorType, CustomFurniture.Placement> placements = new EnumMap<>(AnchorType.class);
|
||||
if (placementMap == null) {
|
||||
throw new IllegalArgumentException("Missing required parameter 'placement' for furniture " + id);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Object> entry : placementMap.entrySet()) {
|
||||
// anchor type
|
||||
AnchorType anchorType = AnchorType.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH));
|
||||
Map<String, Object> placementArguments = MiscUtils.castToMap(entry.getValue(), true);
|
||||
|
||||
// furniture display elements
|
||||
List<FurnitureElement> elements = new ArrayList<>();
|
||||
List<Map<String, Object>> elementConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("elements", List.of());
|
||||
for (Map<String, Object> element : elementConfigs) {
|
||||
String key = (String) element.get("item");
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("Missing required parameter 'item' for furniture " + id);
|
||||
}
|
||||
ItemDisplayContext transform = ItemDisplayContext.valueOf(element.getOrDefault("transform", "NONE").toString().toUpperCase(Locale.ENGLISH));
|
||||
Billboard billboard = Billboard.valueOf(element.getOrDefault("billboard", "FIXED").toString().toUpperCase(Locale.ENGLISH));
|
||||
FurnitureElement furnitureElement = new BukkitFurnitureElement(Key.of(key), billboard, transform,
|
||||
MiscUtils.getVector3f(element.getOrDefault("scale", "1")),
|
||||
MiscUtils.getVector3f(element.getOrDefault("translation", "0")),
|
||||
MiscUtils.getVector3f(element.getOrDefault("position", "0")),
|
||||
MiscUtils.getQuaternionf(element.getOrDefault("rotation", "0"))
|
||||
);
|
||||
elements.add(furnitureElement);
|
||||
}
|
||||
|
||||
// add colliders
|
||||
List<Collider> colliders = new ArrayList<>();
|
||||
|
||||
// external model providers
|
||||
Optional<ExternalModel> externalModel;
|
||||
if (placementArguments.containsKey("model-engine")) {
|
||||
externalModel = Optional.of(new ModelEngineModel(placementArguments.get("model-engine").toString()));
|
||||
} else if (placementArguments.containsKey("better-model")) {
|
||||
externalModel = Optional.of(new BetterModelModel(placementArguments.get("better-model").toString()));
|
||||
} else {
|
||||
externalModel = Optional.empty();
|
||||
}
|
||||
|
||||
// add hitboxes
|
||||
List<Map<String, Object>> hitboxConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("hitboxes", List.of());
|
||||
List<HitBox> hitboxes = new ArrayList<>();
|
||||
for (Map<String, Object> config : hitboxConfigs) {
|
||||
HitBox hitBox = HitBoxTypes.fromMap(config);
|
||||
hitboxes.add(hitBox);
|
||||
hitBox.optionalCollider().ifPresent(colliders::add);
|
||||
}
|
||||
if (hitboxes.isEmpty() && externalModel.isEmpty()) {
|
||||
hitboxes.add(InteractionHitBox.DEFAULT);
|
||||
}
|
||||
|
||||
// rules
|
||||
Map<String, Object> ruleSection = MiscUtils.castToMap(placementArguments.get("rules"), true);
|
||||
if (ruleSection != null) {
|
||||
RotationRule rotationRule = Optional.ofNullable((String) ruleSection.get("rotation"))
|
||||
.map(it -> RotationRule.valueOf(it.toUpperCase(Locale.ENGLISH)))
|
||||
.orElse(RotationRule.ANY);
|
||||
AlignmentRule alignmentRule = Optional.ofNullable((String) ruleSection.get("alignment"))
|
||||
.map(it -> AlignmentRule.valueOf(it.toUpperCase(Locale.ENGLISH)))
|
||||
.orElse(AlignmentRule.CENTER);
|
||||
placements.put(anchorType, new CustomFurniture.Placement(
|
||||
elements.toArray(new FurnitureElement[0]),
|
||||
hitboxes.toArray(new HitBox[0]),
|
||||
colliders.toArray(new Collider[0]),
|
||||
rotationRule,
|
||||
alignmentRule,
|
||||
externalModel
|
||||
));
|
||||
} else {
|
||||
placements.put(anchorType, new CustomFurniture.Placement(
|
||||
elements.toArray(new FurnitureElement[0]),
|
||||
hitboxes.toArray(new HitBox[0]),
|
||||
colliders.toArray(new Collider[0]),
|
||||
RotationRule.ANY,
|
||||
AlignmentRule.CENTER,
|
||||
externalModel
|
||||
));
|
||||
}
|
||||
ItemDisplayContext transform = ItemDisplayContext.valueOf(element.getOrDefault("transform", "NONE").toString().toUpperCase(Locale.ENGLISH));
|
||||
Billboard billboard = Billboard.valueOf(element.getOrDefault("billboard", "FIXED").toString().toUpperCase(Locale.ENGLISH));
|
||||
FurnitureElement furnitureElement = new BukkitFurnitureElement(Key.of(key), billboard, transform,
|
||||
MiscUtils.getVector3f(element.getOrDefault("scale", "1")),
|
||||
MiscUtils.getVector3f(element.getOrDefault("translation", "0")),
|
||||
MiscUtils.getVector3f(element.getOrDefault("position", "0")),
|
||||
MiscUtils.getQuaternionf(element.getOrDefault("rotation", "0"))
|
||||
);
|
||||
elements.add(furnitureElement);
|
||||
}
|
||||
|
||||
// add colliders
|
||||
List<Collider> colliders = new ArrayList<>();
|
||||
// List<Map<String, Object>> colliderConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("colliders", List.of());
|
||||
// for (Map<String, Object> config : colliderConfigs) {
|
||||
// if (!config.containsKey("position")) {
|
||||
// colliders.add(new Collider(
|
||||
// (boolean) config.getOrDefault("can-be-hit-by-projectile", false),
|
||||
// MiscUtils.getVector3d(config.getOrDefault("point-1", "0")),
|
||||
// MiscUtils.getVector3d(config.getOrDefault("point-2", "0"))
|
||||
// ));
|
||||
// } else {
|
||||
// colliders.add(new Collider(
|
||||
// (boolean) config.getOrDefault("can-be-hit-by-projectile", false),
|
||||
// MiscUtils.getVector3f(config.getOrDefault("position", "0")),
|
||||
// MiscUtils.getAsFloat(config.getOrDefault("width", "1")),
|
||||
// MiscUtils.getAsFloat(config.getOrDefault("height", "1"))
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
CustomFurniture furniture = new CustomFurniture(
|
||||
id,
|
||||
FurnitureSettings.fromMap(settingsMap),
|
||||
placements,
|
||||
lootMap == null ? null : LootTable.fromMap(lootMap)
|
||||
);
|
||||
|
||||
// external model providers
|
||||
Optional<ExternalModel> externalModel;
|
||||
if (placementArguments.containsKey("model-engine")) {
|
||||
externalModel = Optional.of(new ModelEngineModel(placementArguments.get("model-engine").toString()));
|
||||
} else if (placementArguments.containsKey("better-model")) {
|
||||
externalModel = Optional.of(new BetterModelModel(placementArguments.get("better-model").toString()));
|
||||
} else {
|
||||
externalModel = Optional.empty();
|
||||
}
|
||||
|
||||
// add hitboxes
|
||||
List<Map<String, Object>> hitboxConfigs = (List<Map<String, Object>>) placementArguments.getOrDefault("hitboxes", List.of());
|
||||
List<HitBox> hitboxes = new ArrayList<>();
|
||||
for (Map<String, Object> config : hitboxConfigs) {
|
||||
HitBox hitBox = HitBoxTypes.fromMap(config);
|
||||
hitboxes.add(hitBox);
|
||||
hitBox.optionalCollider().ifPresent(colliders::add);
|
||||
}
|
||||
if (hitboxes.isEmpty() && externalModel.isEmpty()) {
|
||||
hitboxes.add(InteractionHitBox.DEFAULT);
|
||||
}
|
||||
|
||||
// rules
|
||||
Map<String, Object> ruleSection = MiscUtils.castToMap(placementArguments.get("rules"), true);
|
||||
if (ruleSection != null) {
|
||||
RotationRule rotationRule = Optional.ofNullable((String) ruleSection.get("rotation"))
|
||||
.map(it -> RotationRule.valueOf(it.toUpperCase(Locale.ENGLISH)))
|
||||
.orElse(RotationRule.ANY);
|
||||
AlignmentRule alignmentRule = Optional.ofNullable((String) ruleSection.get("alignment"))
|
||||
.map(it -> AlignmentRule.valueOf(it.toUpperCase(Locale.ENGLISH)))
|
||||
.orElse(AlignmentRule.CENTER);
|
||||
placements.put(anchorType, new CustomFurniture.Placement(
|
||||
elements.toArray(new FurnitureElement[0]),
|
||||
hitboxes.toArray(new HitBox[0]),
|
||||
colliders.toArray(new Collider[0]),
|
||||
rotationRule,
|
||||
alignmentRule,
|
||||
externalModel
|
||||
));
|
||||
} else {
|
||||
placements.put(anchorType, new CustomFurniture.Placement(
|
||||
elements.toArray(new FurnitureElement[0]),
|
||||
hitboxes.toArray(new HitBox[0]),
|
||||
colliders.toArray(new Collider[0]),
|
||||
RotationRule.ANY,
|
||||
AlignmentRule.CENTER,
|
||||
externalModel
|
||||
));
|
||||
}
|
||||
byId.put(id, furniture);
|
||||
}
|
||||
|
||||
CustomFurniture furniture = new CustomFurniture(
|
||||
id,
|
||||
FurnitureSettings.fromMap(settingsMap),
|
||||
placements,
|
||||
lootMap == null ? null : LootTable.fromMap(lootMap)
|
||||
);
|
||||
|
||||
this.byId.put(id, furniture);
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delayedInit() {
|
||||
Bukkit.getPluginManager().registerEvents(this.dismountListener, this.plugin.bootstrap());
|
||||
Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.bootstrap());
|
||||
this.tickTask = plugin.scheduler().sync().runRepeating(this::tick, 1, 1);
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
List<Entity> entities = world.getEntities();
|
||||
for (Entity entity : entities) {
|
||||
@@ -230,18 +212,10 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
this.byId.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
HandlerList.unregisterAll(this.dismountListener);
|
||||
HandlerList.unregisterAll(this.furnitureEventListener);
|
||||
if (tickTask != null && !tickTask.cancelled()) {
|
||||
tickTask.cancel();
|
||||
}
|
||||
unload();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
Entity vehicle = player.getVehicle();
|
||||
@@ -251,23 +225,20 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CustomFurniture> getFurniture(Key id) {
|
||||
return Optional.ofNullable(this.byId.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFurnitureRealEntity(int entityId) {
|
||||
return this.furnitureByRealEntityId.containsKey(entityId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LoadedFurniture getLoadedFurnitureByRealEntityId(int entityId) {
|
||||
@Override
|
||||
public LoadedFurniture loadedFurnitureByRealEntityId(int entityId) {
|
||||
return this.furnitureByRealEntityId.get(entityId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public LoadedFurniture getLoadedFurnitureByEntityId(int entityId) {
|
||||
public LoadedFurniture loadedFurnitureByEntityId(int entityId) {
|
||||
return this.furnitureByEntityId.get(entityId);
|
||||
}
|
||||
|
||||
@@ -296,7 +267,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
String id = entity.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING);
|
||||
if (id == null) return;
|
||||
Key key = Key.of(id);
|
||||
Optional<CustomFurniture> optionalFurniture = getFurniture(key);
|
||||
Optional<CustomFurniture> optionalFurniture = furnitureById(key);
|
||||
if (optionalFurniture.isEmpty()) return;
|
||||
CustomFurniture customFurniture = optionalFurniture.get();
|
||||
LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
|
||||
@@ -318,7 +289,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
String id = entity.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING);
|
||||
if (id == null) return;
|
||||
Key key = Key.of(id);
|
||||
Optional<CustomFurniture> optionalFurniture = getFurniture(key);
|
||||
Optional<CustomFurniture> optionalFurniture = furnitureById(key);
|
||||
if (optionalFurniture.isPresent()) {
|
||||
CustomFurniture customFurniture = optionalFurniture.get();
|
||||
LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
|
||||
@@ -375,7 +346,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
Integer baseFurniture = vehicle.getPersistentDataContainer().get(FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER);
|
||||
if (baseFurniture == null) return;
|
||||
vehicle.remove();
|
||||
LoadedFurniture furniture = getLoadedFurnitureByRealEntityId(baseFurniture);
|
||||
LoadedFurniture furniture = loadedFurnitureByRealEntityId(baseFurniture);
|
||||
if (furniture == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,15 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.ArrayUtils;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.QuaternionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.*;
|
||||
@@ -24,7 +27,7 @@ import org.joml.Vector3f;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
|
||||
public class LoadedFurniture {
|
||||
public class LoadedFurniture implements Furniture {
|
||||
private final Key id;
|
||||
private final CustomFurniture furniture;
|
||||
private final AnchorType anchorType;
|
||||
@@ -144,6 +147,7 @@ public class LoadedFurniture {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeColliders() {
|
||||
Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld());
|
||||
for (CollisionEntity entity : this.collisionEntities) {
|
||||
@@ -161,6 +165,16 @@ public class LoadedFurniture {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3d position() {
|
||||
return new Vec3d(location.getX(), location.getY(), location.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public World world() {
|
||||
return new BukkitWorld(this.location.getWorld());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Location location() {
|
||||
return this.location.clone();
|
||||
@@ -175,10 +189,12 @@ public class LoadedFurniture {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return baseEntity().isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
if (!isValid()) {
|
||||
return;
|
||||
@@ -197,6 +213,7 @@ public class LoadedFurniture {
|
||||
this.seats.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroySeats() {
|
||||
for (Entity entity : this.seats) {
|
||||
entity.remove();
|
||||
@@ -204,6 +221,7 @@ public class LoadedFurniture {
|
||||
this.seats.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Seat> findFirstAvailableSeat(int targetEntityId) {
|
||||
HitBox hitbox = hitBoxes.get(targetEntityId);
|
||||
if (hitbox == null) return Optional.empty();
|
||||
@@ -216,14 +234,12 @@ public class LoadedFurniture {
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOccupiedSeat(Vector3f seat) {
|
||||
return this.occupiedSeats.remove(seat);
|
||||
}
|
||||
|
||||
public boolean removeOccupiedSeat(Seat seat) {
|
||||
return this.removeOccupiedSeat(seat.offset());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryOccupySeat(Seat seat) {
|
||||
if (this.occupiedSeats.contains(seat.offset())) {
|
||||
return false;
|
||||
@@ -232,10 +248,12 @@ public class LoadedFurniture {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID uuid() {
|
||||
return this.baseEntity().getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int baseEntityId() {
|
||||
return this.baseEntityId;
|
||||
}
|
||||
@@ -254,31 +272,29 @@ public class LoadedFurniture {
|
||||
return this.collisionEntities;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AnchorType anchorType() {
|
||||
@Override
|
||||
public @NotNull AnchorType anchorType() {
|
||||
return this.anchorType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Key id() {
|
||||
@Override
|
||||
public @NotNull Key id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CustomFurniture config() {
|
||||
@Override
|
||||
public @NotNull CustomFurniture config() {
|
||||
return this.furniture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExternalModel() {
|
||||
return hasExternalModel;
|
||||
}
|
||||
|
||||
public CustomFurniture.Placement placement() {
|
||||
return this.placement;
|
||||
}
|
||||
|
||||
public Map<Integer, HitBox> hitBoxes() {
|
||||
return this.hitBoxes;
|
||||
@Override
|
||||
public void spawnSeatEntityForPlayer(net.momirealms.craftengine.core.entity.player.Player player, Seat seat) {
|
||||
spawnSeatEntityForPlayer((Player) player.platformPlayer(), seat);
|
||||
}
|
||||
|
||||
public void spawnSeatEntityForPlayer(org.bukkit.entity.Player player, Seat seat) {
|
||||
|
||||
@@ -47,7 +47,7 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
}
|
||||
|
||||
public InteractionResult place(UseOnContext context) {
|
||||
Optional<CustomFurniture> optionalCustomFurniture = BukkitFurnitureManager.instance().getFurniture(this.id);
|
||||
Optional<CustomFurniture> optionalCustomFurniture = BukkitFurnitureManager.instance().furnitureById(this.id);
|
||||
if (optionalCustomFurniture.isEmpty()) {
|
||||
CraftEngine.instance().logger().warn("Furniture " + this.id + " not found");
|
||||
return InteractionResult.FAIL;
|
||||
@@ -139,7 +139,7 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
throw new IllegalArgumentException("Missing required parameter 'furniture' for furniture_item behavior");
|
||||
}
|
||||
if (id instanceof Map<?,?> map) {
|
||||
BukkitFurnitureManager.instance().parseSection(pack, path, key, MiscUtils.castToMap(map, false));
|
||||
BukkitFurnitureManager.instance().parser().parseSection(pack, path, key, MiscUtils.castToMap(map, false));
|
||||
return new FurnitureItemBehavior(key);
|
||||
} else {
|
||||
return new FurnitureItemBehavior(Key.of(id.toString()));
|
||||
|
||||
@@ -47,7 +47,7 @@ public class DebugSpawnFurnitureCommand extends BukkitCommandFeature<CommandSend
|
||||
NamespacedKey namespacedKey = context.get("id");
|
||||
Key id = KeyUtils.namespacedKey2Key(namespacedKey);
|
||||
BukkitFurnitureManager furnitureManager = BukkitFurnitureManager.instance();
|
||||
Optional<CustomFurniture> optionalCustomFurniture = furnitureManager.getFurniture(id);
|
||||
Optional<CustomFurniture> optionalCustomFurniture = furnitureManager.furnitureById(id);
|
||||
if (optionalCustomFurniture.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -563,7 +563,7 @@ public class PacketConsumers {
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> PICK_ITEM_FROM_ENTITY = (user, event, packet) -> {
|
||||
try {
|
||||
int entityId = (int) Reflections.field$ServerboundPickItemFromEntityPacket$id.get(packet);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().getLoadedFurnitureByEntityId(entityId);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
|
||||
if (furniture == null) return;
|
||||
Player player = (Player) user.platformPlayer();
|
||||
if (player == null) return;
|
||||
@@ -622,7 +622,7 @@ public class PacketConsumers {
|
||||
} else if (entityType == Reflections.instance$EntityType$ITEM_DISPLAY) {
|
||||
// Furniture
|
||||
int entityId = (int) Reflections.field$ClientboundAddEntityPacket$entityId.get(packet);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().getLoadedFurnitureByRealEntityId(entityId);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId);
|
||||
if (furniture != null) {
|
||||
user.furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.fakeEntityIds());
|
||||
user.sendPacket(furniture.spawnPacket((Player) user.platformPlayer()), false);
|
||||
@@ -633,7 +633,7 @@ public class PacketConsumers {
|
||||
} else if (entityType == Reflections.instance$EntityType$SHULKER) {
|
||||
// Cancel collider entity packet
|
||||
int entityId = (int) Reflections.field$ClientboundAddEntityPacket$entityId.get(packet);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().getLoadedFurnitureByRealEntityId(entityId);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByRealEntityId(entityId);
|
||||
if (furniture != null) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
@@ -694,7 +694,7 @@ public class PacketConsumers {
|
||||
Object action = Reflections.field$ServerboundInteractPacket$action.get(packet);
|
||||
Object actionType = Reflections.method$ServerboundInteractPacket$Action$getType.invoke(action);
|
||||
if (actionType == null) return;
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().getLoadedFurnitureByEntityId(entityId);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().loadedFurnitureByEntityId(entityId);
|
||||
if (furniture == null) return;
|
||||
Location location = furniture.baseEntity().getLocation();
|
||||
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class AbstractFurnitureManager implements FurnitureManager {
|
||||
protected final Map<Key, CustomFurniture> byId = new HashMap<>();
|
||||
// Cached command suggestions
|
||||
private final List<Suggestion> cachedSuggestions = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void delayedLoad() {
|
||||
this.initSuggestions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSuggestions() {
|
||||
this.cachedSuggestions.clear();
|
||||
for (Key key : this.byId.keySet()) {
|
||||
this.cachedSuggestions.add(Suggestion.suggestion(key.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Suggestion> cachedSuggestions() {
|
||||
return Collections.unmodifiableCollection(this.cachedSuggestions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CustomFurniture> furnitureById(Key id) {
|
||||
return Optional.ofNullable(this.byId.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
this.byId.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Furniture {
|
||||
void initializeColliders();
|
||||
|
||||
Vec3d position();
|
||||
|
||||
World world();
|
||||
|
||||
boolean isValid();
|
||||
|
||||
void destroy();
|
||||
|
||||
void destroySeats();
|
||||
|
||||
Optional<Seat> findFirstAvailableSeat(int targetEntityId);
|
||||
|
||||
boolean removeOccupiedSeat(Vector3f seat);
|
||||
|
||||
default boolean removeOccupiedSeat(Seat seat) {
|
||||
return this.removeOccupiedSeat(seat.offset());
|
||||
}
|
||||
|
||||
boolean tryOccupySeat(Seat seat);
|
||||
|
||||
UUID uuid();
|
||||
|
||||
int baseEntityId();
|
||||
|
||||
@NotNull AnchorType anchorType();
|
||||
|
||||
@NotNull Key id();
|
||||
|
||||
@NotNull CustomFurniture config();
|
||||
|
||||
boolean hasExternalModel();
|
||||
|
||||
void spawnSeatEntityForPlayer(Player player, Seat seat);
|
||||
}
|
||||
@@ -1,33 +1,40 @@
|
||||
package net.momirealms.craftengine.core.entity.furniture;
|
||||
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.entity.Entity;
|
||||
import net.momirealms.craftengine.core.plugin.Reloadable;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface FurnitureManager extends Reloadable, ConfigSectionParser {
|
||||
String[] CONFIG_SECTION_NAME = new String[] { "furniture" };
|
||||
public interface FurnitureManager extends Reloadable {
|
||||
String FURNITURE_ADMIN_NODE = "craftengine.furniture.admin";
|
||||
|
||||
ConfigSectionParser parser();
|
||||
|
||||
void initSuggestions();
|
||||
|
||||
Collection<Suggestion> cachedSuggestions();
|
||||
|
||||
@Override
|
||||
default String[] sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
Furniture place(CustomFurniture furniture, Vec3d vec3d, World world, AnchorType anchorType, boolean playSound);
|
||||
|
||||
@Override
|
||||
default int loadingSequence() {
|
||||
return LoadingSequence.FURNITURE;
|
||||
}
|
||||
|
||||
Optional<CustomFurniture> getFurniture(Key id);
|
||||
Optional<CustomFurniture> furnitureById(Key id);
|
||||
|
||||
boolean isFurnitureRealEntity(int entityId);
|
||||
|
||||
@Nullable
|
||||
Furniture loadedFurnitureByRealEntityId(int entityId);
|
||||
|
||||
@Nullable
|
||||
default Furniture loadedFurnitureByRealEntity(Entity entity) {
|
||||
return loadedFurnitureByRealEntityId(entity.entityID());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Furniture loadedFurnitureByEntityId(int entityId);
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ public abstract class CraftEngine implements Plugin {
|
||||
// register item parser
|
||||
this.packManager.registerConfigSectionParser(this.itemManager);
|
||||
// register furniture parser
|
||||
this.packManager.registerConfigSectionParser(this.furnitureManager);
|
||||
this.packManager.registerConfigSectionParser(this.furnitureManager.parser());
|
||||
// register block parser
|
||||
this.packManager.registerConfigSectionParser(this.blockManager);
|
||||
// register recipe parser
|
||||
|
||||
Reference in New Issue
Block a user