9
0
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:
XiaoMoMi
2025-12-05 20:29:44 +08:00
parent 15593345ea
commit 456dfb00bc
16 changed files with 237 additions and 56 deletions

View File

@@ -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);

View File

@@ -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());

View File

@@ -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);
} }

View File

@@ -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() {}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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) {
} }

View File

@@ -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;

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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();
}
}

View File

@@ -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());

View File

@@ -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")

View File

@@ -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);

View File

@@ -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
* *

View File

@@ -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,21 +51,17 @@ 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();
} }
} }
}
public String name() { public String name() {
return this.world.name(); return this.world.name();
@@ -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;
} }