mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
家具行为API
This commit is contained in:
@@ -26,6 +26,7 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public class BukkitFurniture extends Furniture {
|
public class BukkitFurniture extends Furniture {
|
||||||
private final WeakReference<ItemDisplay> metaEntity;
|
private final WeakReference<ItemDisplay> metaEntity;
|
||||||
private Location location;
|
private Location location;
|
||||||
@@ -54,6 +55,25 @@ public class BukkitFurniture extends Furniture {
|
|||||||
FurnitureVariant variant = this.config.getVariant(variantName);
|
FurnitureVariant variant = this.config.getVariant(variantName);
|
||||||
if (variant == null) return false;
|
if (variant == null) return false;
|
||||||
if (this.currentVariant == variant) return false;
|
if (this.currentVariant == variant) return false;
|
||||||
|
// 检查新位置是否可用
|
||||||
|
List<AABB> aabbs = new ArrayList<>();
|
||||||
|
WorldPosition position = position();
|
||||||
|
for (FurnitureHitBoxConfig<?> hitBoxConfig : variant.hitBoxConfigs()) {
|
||||||
|
hitBoxConfig.prepareBoundingBox(position, aabbs::add, false);
|
||||||
|
}
|
||||||
|
if (!aabbs.isEmpty()) {
|
||||||
|
if (!FastNMS.INSTANCE.checkEntityCollision(position.world.serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList(),
|
||||||
|
o -> {
|
||||||
|
for (Collider collider : super.colliders) {
|
||||||
|
if (o == collider.handle()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
// 删除椅子
|
// 删除椅子
|
||||||
super.destroySeats();
|
super.destroySeats();
|
||||||
BukkitFurnitureManager.instance().invalidateFurniture(this);
|
BukkitFurnitureManager.instance().invalidateFurniture(this);
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
|||||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
|
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.tick.FurnitureTicker;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.tick.TickingFurniture;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.tick.TickingFurnitureImpl;
|
||||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||||
import net.momirealms.craftengine.core.sound.SoundData;
|
import net.momirealms.craftengine.core.sound.SoundData;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
@@ -86,6 +89,8 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void delayedInit() {
|
public void delayedInit() {
|
||||||
|
super.delayedInit();
|
||||||
|
|
||||||
// 确定碰撞箱实体类型
|
// 确定碰撞箱实体类型
|
||||||
COLLISION_ENTITY_TYPE = Config.colliderType();
|
COLLISION_ENTITY_TYPE = Config.colliderType();
|
||||||
COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class;
|
COLLISION_ENTITY_CLASS = Config.colliderType() == ColliderType.INTERACTION ? Interaction.class : Boat.class;
|
||||||
@@ -127,6 +132,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
|
super.disable();
|
||||||
HandlerList.unregisterAll(this.furnitureEventListener);
|
HandlerList.unregisterAll(this.furnitureEventListener);
|
||||||
unload();
|
unload();
|
||||||
}
|
}
|
||||||
@@ -330,19 +336,38 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void initFurniture(BukkitFurniture furniture) {
|
protected void initFurniture(BukkitFurniture furniture) {
|
||||||
this.byMetaEntityId.put(furniture.entityId(), furniture);
|
int entityId = furniture.entityId();
|
||||||
for (int entityId : furniture.virtualEntityIds()) {
|
this.byMetaEntityId.put(entityId, furniture);
|
||||||
this.byVirtualEntityId.put(entityId, furniture);
|
for (int id : furniture.virtualEntityIds()) {
|
||||||
|
this.byVirtualEntityId.put(id, furniture);
|
||||||
}
|
}
|
||||||
for (Collider collisionEntity : furniture.colliders()) {
|
for (Collider collisionEntity : furniture.colliders()) {
|
||||||
this.byColliderEntityId.put(collisionEntity.entityId(), furniture);
|
this.byColliderEntityId.put(collisionEntity.entityId(), furniture);
|
||||||
}
|
}
|
||||||
|
if (!this.syncTickers.containsKey(entityId)) {
|
||||||
|
FurnitureTicker<BukkitFurniture> ticker = furniture.config.behavior().createSyncFurnitureTicker(furniture);
|
||||||
|
if (ticker != null) {
|
||||||
|
TickingFurnitureImpl<BukkitFurniture> tickingFurniture = new TickingFurnitureImpl<>(furniture, ticker);
|
||||||
|
this.syncTickers.put(entityId, tickingFurniture);
|
||||||
|
this.addSyncFurnitureTicker(tickingFurniture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.asyncTickers.containsKey(entityId)) {
|
||||||
|
FurnitureTicker<BukkitFurniture> ticker = furniture.config.behavior().createAsyncBlockEntityTicker(furniture);
|
||||||
|
if (ticker != null) {
|
||||||
|
TickingFurnitureImpl<BukkitFurniture> tickingFurniture = new TickingFurnitureImpl<>(furniture, ticker);
|
||||||
|
this.asyncTickers.put(entityId, tickingFurniture);
|
||||||
|
this.addAsyncFurnitureTicker(tickingFurniture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void invalidateFurniture(BukkitFurniture furniture) {
|
protected void invalidateFurniture(BukkitFurniture furniture) {
|
||||||
this.byMetaEntityId.remove(furniture.entityId());
|
int entityId = furniture.entityId();
|
||||||
for (int entityId : furniture.virtualEntityIds()) {
|
// 移除entity id映射
|
||||||
this.byVirtualEntityId.remove(entityId);
|
this.byMetaEntityId.remove(entityId);
|
||||||
|
for (int id : furniture.virtualEntityIds()) {
|
||||||
|
this.byVirtualEntityId.remove(id);
|
||||||
}
|
}
|
||||||
for (Collider collisionEntity : furniture.colliders()) {
|
for (Collider collisionEntity : furniture.colliders()) {
|
||||||
this.byColliderEntityId.remove(collisionEntity.entityId());
|
this.byColliderEntityId.remove(collisionEntity.entityId());
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture;
|
package net.momirealms.craftengine.core.entity.furniture;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import net.momirealms.craftengine.core.block.entity.tick.TickingBlockEntity;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehaviorTypes;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig;
|
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigs;
|
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigs;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
|
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxConfig;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxTypes;
|
import net.momirealms.craftengine.core.entity.furniture.hitbox.FurnitureHitBoxTypes;
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.tick.TickingFurniture;
|
||||||
import net.momirealms.craftengine.core.loot.LootTable;
|
import net.momirealms.craftengine.core.loot.LootTable;
|
||||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||||
import net.momirealms.craftengine.core.pack.Pack;
|
import net.momirealms.craftengine.core.pack.Pack;
|
||||||
@@ -14,10 +18,8 @@ import net.momirealms.craftengine.core.plugin.config.IdSectionConfigParser;
|
|||||||
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
|
import net.momirealms.craftengine.core.plugin.context.event.EventFunctions;
|
||||||
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
|
import net.momirealms.craftengine.core.plugin.entityculling.CullingData;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.*;
|
||||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
|
||||||
import org.incendo.cloud.suggestion.Suggestion;
|
import org.incendo.cloud.suggestion.Suggestion;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
@@ -31,6 +33,18 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
// Cached command suggestions
|
// Cached command suggestions
|
||||||
private final List<Suggestion> cachedSuggestions = new ArrayList<>();
|
private final List<Suggestion> cachedSuggestions = new ArrayList<>();
|
||||||
|
|
||||||
|
protected final Int2ObjectOpenHashMap<TickingFurniture> syncTickers = new Int2ObjectOpenHashMap<>(256, 0.5f);
|
||||||
|
protected final Int2ObjectOpenHashMap<TickingFurniture> asyncTickers = new Int2ObjectOpenHashMap<>(256, 0.5f);
|
||||||
|
protected final TickersList<TickingFurniture> syncTickingFurniture = new TickersList<>();
|
||||||
|
protected final List<TickingFurniture> pendingSyncTickingFurniture = new ArrayList<>();
|
||||||
|
protected final TickersList<TickingFurniture> asyncTickingFurniture = new TickersList<>();
|
||||||
|
protected final List<TickingFurniture> pendingAsyncTickingFurniture = new ArrayList<>();
|
||||||
|
private boolean isTickingSyncFurniture = false;
|
||||||
|
private boolean isTickingAsyncFurniture = false;
|
||||||
|
|
||||||
|
protected SchedulerTask syncTickTask;
|
||||||
|
protected SchedulerTask asyncTickTask;
|
||||||
|
|
||||||
public AbstractFurnitureManager(CraftEngine plugin) {
|
public AbstractFurnitureManager(CraftEngine plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.furnitureParser = new FurnitureParser();
|
this.furnitureParser = new FurnitureParser();
|
||||||
@@ -69,6 +83,82 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
return Collections.unmodifiableMap(this.byId);
|
return Collections.unmodifiableMap(this.byId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncTick() {
|
||||||
|
this.isTickingSyncFurniture = true;
|
||||||
|
if (!this.pendingSyncTickingFurniture.isEmpty()) {
|
||||||
|
this.syncTickingFurniture.addAll(this.pendingSyncTickingFurniture);
|
||||||
|
this.pendingSyncTickingFurniture.clear();
|
||||||
|
}
|
||||||
|
if (!this.syncTickingFurniture.isEmpty()) {
|
||||||
|
Object[] entities = this.syncTickingFurniture.elements();
|
||||||
|
for (int i = 0, size = this.syncTickingFurniture.size(); i < size; i++) {
|
||||||
|
TickingFurniture entity = (TickingFurniture) entities[i];
|
||||||
|
if (entity.isValid()) {
|
||||||
|
entity.tick();
|
||||||
|
} else {
|
||||||
|
this.syncTickingFurniture.markAsRemoved(i);
|
||||||
|
this.syncTickers.remove(entity.entityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.syncTickingFurniture.removeMarkedEntries();
|
||||||
|
}
|
||||||
|
this.isTickingSyncFurniture = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void asyncTick() {
|
||||||
|
this.isTickingAsyncFurniture = true;
|
||||||
|
if (!this.pendingAsyncTickingFurniture.isEmpty()) {
|
||||||
|
this.asyncTickingFurniture.addAll(this.pendingAsyncTickingFurniture);
|
||||||
|
this.pendingAsyncTickingFurniture.clear();
|
||||||
|
}
|
||||||
|
if (!this.asyncTickingFurniture.isEmpty()) {
|
||||||
|
Object[] entities = this.asyncTickingFurniture.elements();
|
||||||
|
for (int i = 0, size = this.asyncTickingFurniture.size(); i < size; i++) {
|
||||||
|
TickingFurniture entity = (TickingFurniture) entities[i];
|
||||||
|
if (entity.isValid()) {
|
||||||
|
entity.tick();
|
||||||
|
} else {
|
||||||
|
this.asyncTickingFurniture.markAsRemoved(i);
|
||||||
|
this.asyncTickers.remove(entity.entityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.asyncTickingFurniture.removeMarkedEntries();
|
||||||
|
}
|
||||||
|
this.isTickingAsyncFurniture = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addSyncFurnitureTicker(TickingFurniture ticker) {
|
||||||
|
if (this.isTickingSyncFurniture) {
|
||||||
|
this.pendingSyncTickingFurniture.add(ticker);
|
||||||
|
} else {
|
||||||
|
this.syncTickingFurniture.add(ticker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addAsyncFurnitureTicker(TickingFurniture ticker) {
|
||||||
|
if (this.isTickingAsyncFurniture) {
|
||||||
|
this.pendingAsyncTickingFurniture.add(ticker);
|
||||||
|
} else {
|
||||||
|
this.asyncTickingFurniture.add(ticker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delayedInit() {
|
||||||
|
if (this.syncTickTask == null || this.syncTickTask.cancelled())
|
||||||
|
this.syncTickTask = CraftEngine.instance().scheduler().sync().runRepeating(this::syncTick, 1, 1);
|
||||||
|
if (this.asyncTickTask == null || this.asyncTickTask.cancelled())
|
||||||
|
this.asyncTickTask = CraftEngine.instance().scheduler().sync().runAsyncRepeating(this::asyncTick, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disable() {
|
||||||
|
if (this.syncTickTask != null && !this.syncTickTask.cancelled())
|
||||||
|
this.syncTickTask.cancel();
|
||||||
|
if (this.asyncTickTask != null && !this.asyncTickTask.cancelled())
|
||||||
|
this.asyncTickTask.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unload() {
|
public void unload() {
|
||||||
this.byId.clear();
|
this.byId.clear();
|
||||||
@@ -160,6 +250,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
.variants(variants)
|
.variants(variants)
|
||||||
.events(EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")))
|
.events(EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event")))
|
||||||
.lootTable(LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), true)))
|
.lootTable(LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), true)))
|
||||||
|
.behavior(FurnitureBehaviorTypes.fromMap(ResourceConfigUtils.getAsMapOrNull(ResourceConfigUtils.get(section, "behaviors", "behavior"), "behavior")))
|
||||||
.build();
|
.build();
|
||||||
AbstractFurnitureManager.this.byId.put(id, furniture);
|
AbstractFurnitureManager.this.byId.put(id, furniture);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture.behavior;
|
package net.momirealms.craftengine.core.entity.furniture.behavior;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
public final class EmptyFurnitureBehavior implements FurnitureBehavior {
|
public final class EmptyFurnitureBehavior implements FurnitureBehavior {
|
||||||
private EmptyFurnitureBehavior() {}
|
private EmptyFurnitureBehavior() {}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package net.momirealms.craftengine.core.entity.furniture.behavior;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||||
import net.momirealms.craftengine.core.entity.furniture.tick.FurnitureTicker;
|
import net.momirealms.craftengine.core.entity.furniture.tick.FurnitureTicker;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
public interface FurnitureBehavior {
|
public interface FurnitureBehavior {
|
||||||
|
|
||||||
default <T extends Furniture> FurnitureTicker<T> createSyncFurnitureTicker(T furniture) {
|
default <T extends Furniture> FurnitureTicker<T> createSyncFurnitureTicker(T furniture) {
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture.behavior;
|
package net.momirealms.craftengine.core.entity.furniture.behavior;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
public interface FurnitureBehaviorFactory<T extends FurnitureBehavior> {
|
public interface FurnitureBehaviorFactory<T extends FurnitureBehavior> {
|
||||||
|
|
||||||
T create(Map<String, Object> properties);
|
T create(Map<String, Object> properties);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture.behavior;
|
package net.momirealms.craftengine.core.entity.furniture.behavior;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
public record FurnitureBehaviorType<T extends FurnitureBehavior>(Key id, FurnitureBehaviorFactory<T> factory) {
|
public record FurnitureBehaviorType<T extends FurnitureBehavior>(Key id, FurnitureBehaviorFactory<T> factory) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import net.momirealms.craftengine.core.registry.WritableRegistry;
|
|||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
import net.momirealms.craftengine.core.util.ResourceKey;
|
import net.momirealms.craftengine.core.util.ResourceKey;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
public class FurnitureBehaviorTypes {
|
public class FurnitureBehaviorTypes {
|
||||||
public static final Key EMPTY = Key.from("craftengine:empty");
|
|
||||||
|
|
||||||
public static FurnitureBehavior fromMap(@Nullable Map<String, Object> map) {
|
public static FurnitureBehavior fromMap(@Nullable Map<String, Object> map) {
|
||||||
if (map == null || map.isEmpty()) return EmptyFurnitureBehavior.INSTANCE;
|
if (map == null || map.isEmpty()) return EmptyFurnitureBehavior.INSTANCE;
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package net.momirealms.craftengine.core.entity.furniture.tick;
|
package net.momirealms.craftengine.core.entity.furniture.tick;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
public interface FurnitureTicker<T extends Furniture> {
|
public interface FurnitureTicker<T extends Furniture> {
|
||||||
|
|
||||||
void tick(T furniture);
|
void tick(T furniture);
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.furniture.tick;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
public interface TickingFurniture {
|
||||||
|
|
||||||
|
void tick();
|
||||||
|
|
||||||
|
boolean isValid();
|
||||||
|
|
||||||
|
int entityId();
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package net.momirealms.craftengine.core.entity.furniture.tick;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.entity.furniture.Furniture;
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
public class TickingFurnitureImpl<T extends Furniture> implements TickingFurniture {
|
||||||
|
private final T furniture;
|
||||||
|
private final FurnitureTicker<T> ticker;
|
||||||
|
|
||||||
|
public TickingFurnitureImpl(T furniture, FurnitureTicker<T> ticker) {
|
||||||
|
this.furniture = furniture;
|
||||||
|
this.ticker = ticker;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
this.ticker.tick(this.furniture);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return this.furniture.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int entityId() {
|
||||||
|
return this.furniture.entityId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -133,12 +133,12 @@ public abstract class AbstractRecipeSerializer<T, R extends Recipe<T>> implement
|
|||||||
return new CustomRecipeResult<>(CloneableConstantItem.of(result), recipeResult.count(), null);
|
return new CustomRecipeResult<>(CloneableConstantItem.of(result), recipeResult.count(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
protected Ingredient<T> toIngredient(String item) {
|
protected Ingredient<T> toIngredient(String item) {
|
||||||
return toIngredient(List.of(item));
|
return toIngredient(List.of(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
protected Ingredient<T> toIngredient(List<String> items) {
|
protected Ingredient<T> toIngredient(List<String> items) {
|
||||||
Set<UniqueKey> itemIds = new HashSet<>();
|
Set<UniqueKey> itemIds = new HashSet<>();
|
||||||
Set<UniqueKey> minecraftItemIds = new HashSet<>();
|
Set<UniqueKey> minecraftItemIds = new HashSet<>();
|
||||||
@@ -149,6 +149,9 @@ public abstract class AbstractRecipeSerializer<T, R extends Recipe<T>> implement
|
|||||||
Key tag = Key.of(item.substring(1));
|
Key tag = Key.of(item.substring(1));
|
||||||
elements.add(new IngredientElement.Tag(tag));
|
elements.add(new IngredientElement.Tag(tag));
|
||||||
List<UniqueKey> uniqueKeys = itemManager.itemIdsByTag(tag);
|
List<UniqueKey> uniqueKeys = itemManager.itemIdsByTag(tag);
|
||||||
|
if (uniqueKeys.isEmpty()) {
|
||||||
|
throw new LocalizedResourceConfigException("warning.config.recipe.invalid_ingredient", item);
|
||||||
|
}
|
||||||
itemIds.addAll(uniqueKeys);
|
itemIds.addAll(uniqueKeys);
|
||||||
for (UniqueKey uniqueKey : uniqueKeys) {
|
for (UniqueKey uniqueKey : uniqueKeys) {
|
||||||
List<UniqueKey> ingredientSubstitutes = itemManager.getIngredientSubstitutes(uniqueKey.key());
|
List<UniqueKey> ingredientSubstitutes = itemManager.getIngredientSubstitutes(uniqueKey.key());
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import net.momirealms.craftengine.core.util.Key;
|
|||||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -37,12 +38,12 @@ public class CustomShapelessRecipe<T> extends CustomCraftingTableRecipe<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PlacementInfo<T> placementInfo() {
|
public PlacementInfo<T> placementInfo() {
|
||||||
return placementInfo;
|
return this.placementInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Ingredient<T>> ingredientsInUse() {
|
public List<Ingredient<T>> ingredientsInUse() {
|
||||||
return ingredients;
|
return this.ingredients;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class PlacementInfo<T> {
|
|||||||
IntList intList = new IntArrayList(i);
|
IntList intList = new IntArrayList(i);
|
||||||
for (int j = 0; j < i; j++) {
|
for (int j = 0; j < i; j++) {
|
||||||
Ingredient<T> ingredient = ingredients.get(j);
|
Ingredient<T> ingredient = ingredients.get(j);
|
||||||
if (ingredient.isEmpty()) {
|
if (ingredient == null || ingredient.isEmpty()) {
|
||||||
return new PlacementInfo<>(List.of(), IntList.of());
|
return new PlacementInfo<>(List.of(), IntList.of());
|
||||||
}
|
}
|
||||||
intList.add(j);
|
intList.add(j);
|
||||||
|
|||||||
@@ -6,10 +6,8 @@ package net.momirealms.craftengine.core.util;
|
|||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import net.momirealms.craftengine.core.block.entity.tick.TickingBlockEntity;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list for ServerLevel's blockEntityTickers
|
* A list for ServerLevel's blockEntityTickers
|
||||||
@@ -20,26 +18,17 @@ import java.util.Collection;
|
|||||||
* This is faster than using removeAll, since we don't need to compare the identity of each block entity, and faster than looping thru each index manually and deleting with remove,
|
* This is faster than using removeAll, since we don't need to compare the identity of each block entity, and faster than looping thru each index manually and deleting with remove,
|
||||||
* since we don't need to resize the array every single remove.
|
* since we don't need to resize the array every single remove.
|
||||||
*/
|
*/
|
||||||
public final class BlockEntityTickersList extends ObjectArrayList<TickingBlockEntity> {
|
public final class TickersList<T> extends ObjectArrayList<T> {
|
||||||
private final IntOpenHashSet toRemove = new IntOpenHashSet();
|
private final IntOpenHashSet toRemove = new IntOpenHashSet();
|
||||||
private int startSearchFromIndex = -1;
|
private int startSearchFromIndex = -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
* Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
||||||
*/
|
*/
|
||||||
public BlockEntityTickersList() {
|
public TickersList() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new array list and fills it with a given collection.
|
|
||||||
*
|
|
||||||
* @param c a collection that will be used to fill the array list.
|
|
||||||
*/
|
|
||||||
public BlockEntityTickersList(final Collection<? extends TickingBlockEntity> c) {
|
|
||||||
super(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks an entry as removed
|
* Marks an entry as removed
|
||||||
*
|
*
|
||||||
@@ -7,7 +7,7 @@ import net.momirealms.craftengine.core.block.entity.tick.TickingBlockEntity;
|
|||||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
||||||
import net.momirealms.craftengine.core.util.BlockEntityTickersList;
|
import net.momirealms.craftengine.core.util.TickersList;
|
||||||
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
import net.momirealms.craftengine.core.world.chunk.CEChunk;
|
||||||
import net.momirealms.craftengine.core.world.chunk.storage.StorageAdaptor;
|
import net.momirealms.craftengine.core.world.chunk.storage.StorageAdaptor;
|
||||||
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
|
import net.momirealms.craftengine.core.world.chunk.storage.WorldDataStorage;
|
||||||
@@ -25,9 +25,9 @@ public abstract class CEWorld {
|
|||||||
protected final WorldHeight worldHeightAccessor;
|
protected final WorldHeight worldHeightAccessor;
|
||||||
protected List<SectionPos> pendingLightSections = new ArrayList<>();
|
protected List<SectionPos> pendingLightSections = new ArrayList<>();
|
||||||
protected final Set<SectionPos> lightSections = ConcurrentHashMap.newKeySet(128);
|
protected final Set<SectionPos> lightSections = ConcurrentHashMap.newKeySet(128);
|
||||||
protected final BlockEntityTickersList tickingSyncBlockEntities = new BlockEntityTickersList();
|
protected final TickersList<TickingBlockEntity> syncTickingBlockEntities = new TickersList<>();
|
||||||
protected final List<TickingBlockEntity> pendingSyncTickingBlockEntities = new ArrayList<>();
|
protected final List<TickingBlockEntity> pendingSyncTickingBlockEntities = new ArrayList<>();
|
||||||
protected final BlockEntityTickersList tickingAsyncBlockEntities = new BlockEntityTickersList();
|
protected final TickersList<TickingBlockEntity> asyncTickingBlockEntities = new TickersList<>();
|
||||||
protected final List<TickingBlockEntity> pendingAsyncTickingBlockEntities = new ArrayList<>();
|
protected final List<TickingBlockEntity> pendingAsyncTickingBlockEntities = new ArrayList<>();
|
||||||
protected volatile boolean isTickingSyncBlockEntities = false;
|
protected volatile boolean isTickingSyncBlockEntities = false;
|
||||||
protected volatile boolean isTickingAsyncBlockEntities = false;
|
protected volatile boolean isTickingAsyncBlockEntities = false;
|
||||||
@@ -51,19 +51,15 @@ public abstract class CEWorld {
|
|||||||
|
|
||||||
public void setTicking(boolean ticking) {
|
public void setTicking(boolean ticking) {
|
||||||
if (ticking) {
|
if (ticking) {
|
||||||
if (this.syncTickTask == null || this.syncTickTask.cancelled()) {
|
if (this.syncTickTask == null || this.syncTickTask.cancelled())
|
||||||
this.syncTickTask = CraftEngine.instance().scheduler().sync().runRepeating(this::syncTick, 1, 1);
|
this.syncTickTask = CraftEngine.instance().scheduler().sync().runRepeating(this::syncTick, 1, 1);
|
||||||
}
|
if (this.asyncTickTask == null || this.asyncTickTask.cancelled())
|
||||||
if (this.asyncTickTask == null || this.asyncTickTask.cancelled()) {
|
|
||||||
this.asyncTickTask = CraftEngine.instance().scheduler().sync().runAsyncRepeating(this::asyncTick, 1, 1);
|
this.asyncTickTask = CraftEngine.instance().scheduler().sync().runAsyncRepeating(this::asyncTick, 1, 1);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (this.syncTickTask != null && !this.syncTickTask.cancelled()) {
|
if (this.syncTickTask != null && !this.syncTickTask.cancelled())
|
||||||
this.syncTickTask.cancel();
|
this.syncTickTask.cancel();
|
||||||
}
|
if (this.asyncTickTask != null && !this.asyncTickTask.cancelled())
|
||||||
if (this.asyncTickTask != null && !this.asyncTickTask.cancelled()) {
|
|
||||||
this.asyncTickTask.cancel();
|
this.asyncTickTask.cancel();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,39 +190,39 @@ public abstract class CEWorld {
|
|||||||
|
|
||||||
public abstract void updateLight();
|
public abstract void updateLight();
|
||||||
|
|
||||||
public void addSyncBlockEntityTicker(TickingBlockEntity ticker) {
|
public synchronized void addSyncBlockEntityTicker(TickingBlockEntity ticker) {
|
||||||
if (this.isTickingSyncBlockEntities) {
|
if (this.isTickingSyncBlockEntities) {
|
||||||
this.pendingSyncTickingBlockEntities.add(ticker);
|
this.pendingSyncTickingBlockEntities.add(ticker);
|
||||||
} else {
|
} else {
|
||||||
this.tickingSyncBlockEntities.add(ticker);
|
this.syncTickingBlockEntities.add(ticker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAsyncBlockEntityTicker(TickingBlockEntity ticker) {
|
public synchronized void addAsyncBlockEntityTicker(TickingBlockEntity ticker) {
|
||||||
if (this.isTickingAsyncBlockEntities) {
|
if (this.isTickingAsyncBlockEntities) {
|
||||||
this.pendingAsyncTickingBlockEntities.add(ticker);
|
this.pendingAsyncTickingBlockEntities.add(ticker);
|
||||||
} else {
|
} else {
|
||||||
this.tickingAsyncBlockEntities.add(ticker);
|
this.asyncTickingBlockEntities.add(ticker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tickSyncBlockEntities() {
|
protected void tickSyncBlockEntities() {
|
||||||
this.isTickingSyncBlockEntities = true;
|
this.isTickingSyncBlockEntities = true;
|
||||||
if (!this.pendingSyncTickingBlockEntities.isEmpty()) {
|
if (!this.pendingSyncTickingBlockEntities.isEmpty()) {
|
||||||
this.tickingSyncBlockEntities.addAll(this.pendingSyncTickingBlockEntities);
|
this.syncTickingBlockEntities.addAll(this.pendingSyncTickingBlockEntities);
|
||||||
this.pendingSyncTickingBlockEntities.clear();
|
this.pendingSyncTickingBlockEntities.clear();
|
||||||
}
|
}
|
||||||
if (!this.tickingSyncBlockEntities.isEmpty()) {
|
if (!this.syncTickingBlockEntities.isEmpty()) {
|
||||||
Object[] entities = this.tickingSyncBlockEntities.elements();
|
Object[] entities = this.syncTickingBlockEntities.elements();
|
||||||
for (int i = 0, size = this.tickingSyncBlockEntities.size(); i < size; i++) {
|
for (int i = 0, size = this.syncTickingBlockEntities.size(); i < size; i++) {
|
||||||
TickingBlockEntity entity = (TickingBlockEntity) entities[i];
|
TickingBlockEntity entity = (TickingBlockEntity) entities[i];
|
||||||
if (entity.isValid()) {
|
if (entity.isValid()) {
|
||||||
entity.tick();
|
entity.tick();
|
||||||
} else {
|
} else {
|
||||||
this.tickingSyncBlockEntities.markAsRemoved(i);
|
this.syncTickingBlockEntities.markAsRemoved(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tickingSyncBlockEntities.removeMarkedEntries();
|
this.syncTickingBlockEntities.removeMarkedEntries();
|
||||||
}
|
}
|
||||||
this.isTickingSyncBlockEntities = false;
|
this.isTickingSyncBlockEntities = false;
|
||||||
}
|
}
|
||||||
@@ -234,20 +230,20 @@ public abstract class CEWorld {
|
|||||||
protected void tickAsyncBlockEntities() {
|
protected void tickAsyncBlockEntities() {
|
||||||
this.isTickingAsyncBlockEntities = true;
|
this.isTickingAsyncBlockEntities = true;
|
||||||
if (!this.pendingAsyncTickingBlockEntities.isEmpty()) {
|
if (!this.pendingAsyncTickingBlockEntities.isEmpty()) {
|
||||||
this.tickingAsyncBlockEntities.addAll(this.pendingAsyncTickingBlockEntities);
|
this.asyncTickingBlockEntities.addAll(this.pendingAsyncTickingBlockEntities);
|
||||||
this.pendingAsyncTickingBlockEntities.clear();
|
this.pendingAsyncTickingBlockEntities.clear();
|
||||||
}
|
}
|
||||||
if (!this.tickingAsyncBlockEntities.isEmpty()) {
|
if (!this.asyncTickingBlockEntities.isEmpty()) {
|
||||||
Object[] entities = this.tickingAsyncBlockEntities.elements();
|
Object[] entities = this.asyncTickingBlockEntities.elements();
|
||||||
for (int i = 0, size = this.tickingAsyncBlockEntities.size(); i < size; i++) {
|
for (int i = 0, size = this.asyncTickingBlockEntities.size(); i < size; i++) {
|
||||||
TickingBlockEntity entity = (TickingBlockEntity) entities[i];
|
TickingBlockEntity entity = (TickingBlockEntity) entities[i];
|
||||||
if (entity.isValid()) {
|
if (entity.isValid()) {
|
||||||
entity.tick();
|
entity.tick();
|
||||||
} else {
|
} else {
|
||||||
this.tickingAsyncBlockEntities.markAsRemoved(i);
|
this.asyncTickingBlockEntities.markAsRemoved(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.tickingAsyncBlockEntities.removeMarkedEntries();
|
this.asyncTickingBlockEntities.removeMarkedEntries();
|
||||||
}
|
}
|
||||||
this.isTickingAsyncBlockEntities = false;
|
this.isTickingAsyncBlockEntities = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user