Improve MobSpawns and BlockEntities prep to palette changes

This commit is contained in:
Taiyou06
2024-07-10 03:47:04 +03:00
parent 4aa707b8b5
commit cd9e06fea7
8 changed files with 578 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
package net.gensokyoreimagined.nitori.common.world.blockentity;
public interface SupportCache {
boolean lithium$isSupported();
}

View File

@@ -0,0 +1,197 @@
package net.gensokyoreimagined.nitori.common.world.chunk;
//import com.google.common.collect.ImmutableList;
//import it.unimi.dsi.fastutil.HashCommon;
//import it.unimi.dsi.fastutil.objects.Reference2IntMap;
//import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
//import net.minecraft.network.FriendlyByteBuf;
//import net.minecraft.network.VarInt;
//import net.minecraft.core.IdMap;
//import net.minecraft.world.level.chunk.MissingPaletteEntryException;
//import net.minecraft.world.level.chunk.Palette;
//import net.minecraft.world.level.chunk.PaletteResize;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.function.Predicate;
//
//import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR;
//
///**
// * Generally provides better performance over the vanilla {@link net.minecraft.world.chunk.BiMapPalette} when calling
// * {@link LithiumHashPalette#index(Object)} through using a faster backing map and reducing pointer chasing.
// */
//public class LithiumHashPalette<T> implements Palette<T> {
// private static final int ABSENT_VALUE = -1;
//
// private final IdMap<T> idList;
// private final PaletteResize<T> resizeHandler;
// private final int indexBits;
//
// private final Reference2IntMap<T> table;
// private T[] entries;
// private int size = 0;
//
// public LithiumHashPalette(IdMap<T> idList, PaletteResize<T> resizeHandler, int indexBits, T[] entries, Reference2IntMap<T> table, int size) {
// this.idList = idList;
// this.resizeHandler = resizeHandler;
// this.indexBits = indexBits;
// this.entries = entries;
// this.table = table;
// this.size = size;
// }
//
// public LithiumHashPalette(IdMap<T> idList, int bits, PaletteResizeListener<T> resizeHandler, List<T> list) {
// this(idList, bits, resizeHandler);
//
// for (T t : list) {
// this.addEntry(t);
// }
// }
//
// @SuppressWarnings("unchecked")
// public LithiumHashPalette(IdMap<T> idList, int bits, PaletteResizeListener<T> resizeHandler) {
// this.idList = idList;
// this.indexBits = bits;
// this.resizeHandler = resizeHandler;
//
// int capacity = 1 << bits;
//
// this.entries = (T[]) new Object[capacity];
// this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR);
// this.table.defaultReturnValue(ABSENT_VALUE);
// }
//
// @Override
// public int index(T obj) {
// int id = this.table.getInt(obj);
//
// if (id == ABSENT_VALUE) {
// id = this.computeEntry(obj);
// }
//
// return id;
// }
//
// @Override
// public boolean hasAny(Predicate<T> predicate) {
// for (int i = 0; i < this.size; ++i) {
// if (predicate.test(this.entries[i])) {
// return true;
// }
// }
//
// return false;
// }
//
// private int computeEntry(T obj) {
// int id = this.addEntry(obj);
//
// if (id >= 1 << this.indexBits) {
// if (this.resizeHandler == null) {
// throw new IllegalStateException("Cannot grow");
// } else {
// id = this.resizeHandler.onResize(this.indexBits + 1, obj);
// }
// }
//
// return id;
// }
//
// private int addEntry(T obj) {
// int nextId = this.size;
//
// if (nextId >= this.entries.length) {
// this.resize(this.size);
// }
//
// this.table.put(obj, nextId);
// this.entries[nextId] = obj;
//
// this.size++;
//
// return nextId;
// }
//
// private void resize(int neededCapacity) {
// this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1));
// }
//
// @Override
// public T get(int id) {
// T[] entries = this.entries;
//
// T entry = null;
// if (id >= 0 && id < entries.length) {
// entry = entries[id];
// }
//
// if (entry != null) {
// return entry;
// } else {
// throw new MissingPaletteEntryException(id);
// }
// }
//
// @Override
// public void readPacket(FriendlyByteBuf buf) {
// this.clear();
//
// int entryCount = buf.readVarInt();
//
// for (int i = 0; i < entryCount; ++i) {
// this.addEntry(this.idList.get(buf.readVarInt()));
// }
// }
//
// @Override
// public void writePacket(FriendlyByteBuf buf) {
// int size = this.size;
// buf.writeVarInt(size);
//
// for (int i = 0; i < size; ++i) {
// buf.writeVarInt(this.idList.getRawId(this.get(i)));
// }
// }
//
// @Override
// public int getPacketSize() {
// int size = VarInt.getSizeInBytes(this.size);
//
// for (int i = 0; i < this.size; ++i) {
// size += VarInt.getSizeInBytes(this.idList.getRawId(this.get(i)));
// }
//
// return size;
// }
//
// @Override
// public int getSize() {
// return this.size;
// }
//
// @Override
// public Palette<T> copy() {
// return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size);
// }
//
// private void clear() {
// Arrays.fill(this.entries, null);
// this.table.clear();
// this.size = 0;
// }
//
// public List<T> getElements() {
// ImmutableList.Builder<T> builder = new ImmutableList.Builder<>();
// for (T entry : this.entries) {
// if (entry != null) {
// builder.add(entry);
// }
// }
// return builder.build();
// }
//
// public static <A> Palette<A> create(int bits, IdMap<A> idList, PaletteResizeListener<A> listener, List<A> list) {
// return new LithiumHashPalette<>(idList, bits, listener, list);
// }
//}

View File

@@ -0,0 +1,197 @@
package net.gensokyoreimagined.nitori.mixin.chunk.palette;
//import com.google.common.collect.ImmutableList;
//import it.unimi.dsi.fastutil.HashCommon;
//import it.unimi.dsi.fastutil.objects.Reference2IntMap;
//import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
//import net.minecraft.network.PacketByteBuf;
//import net.minecraft.network.encoding.VarInts;
//import net.minecraft.util.collection.IndexedIterable;
//import net.minecraft.world.chunk.EntryMissingException;
//import net.minecraft.world.chunk.Palette;
//import net.minecraft.world.chunk.PaletteResizeListener;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.function.Predicate;
//
//import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR;
//
///**
// * Generally provides better performance over the vanilla {@link net.minecraft.world.chunk.BiMapPalette} when calling
// * {@link LithiumHashPalette#index(Object)} through using a faster backing map and reducing pointer chasing.
// */
//public class LithiumHashPalette<T> implements Palette<T> {
// private static final int ABSENT_VALUE = -1;
//
// private final IndexedIterable<T> idList;
// private final PaletteResizeListener<T> resizeHandler;
// private final int indexBits;
//
// private final Reference2IntMap<T> table;
// private T[] entries;
// private int size = 0;
//
// public LithiumHashPalette(IndexedIterable<T> idList, PaletteResizeListener<T> resizeHandler, int indexBits, T[] entries, Reference2IntMap<T> table, int size) {
// this.idList = idList;
// this.resizeHandler = resizeHandler;
// this.indexBits = indexBits;
// this.entries = entries;
// this.table = table;
// this.size = size;
// }
//
// public LithiumHashPalette(IndexedIterable<T> idList, int bits, PaletteResizeListener<T> resizeHandler, List<T> list) {
// this(idList, bits, resizeHandler);
//
// for (T t : list) {
// this.addEntry(t);
// }
// }
//
// @SuppressWarnings("unchecked")
// public LithiumHashPalette(IndexedIterable<T> idList, int bits, PaletteResizeListener<T> resizeHandler) {
// this.idList = idList;
// this.indexBits = bits;
// this.resizeHandler = resizeHandler;
//
// int capacity = 1 << bits;
//
// this.entries = (T[]) new Object[capacity];
// this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR);
// this.table.defaultReturnValue(ABSENT_VALUE);
// }
//
// @Override
// public int index(T obj) {
// int id = this.table.getInt(obj);
//
// if (id == ABSENT_VALUE) {
// id = this.computeEntry(obj);
// }
//
// return id;
// }
//
// @Override
// public boolean hasAny(Predicate<T> predicate) {
// for (int i = 0; i < this.size; ++i) {
// if (predicate.test(this.entries[i])) {
// return true;
// }
// }
//
// return false;
// }
//
// private int computeEntry(T obj) {
// int id = this.addEntry(obj);
//
// if (id >= 1 << this.indexBits) {
// if (this.resizeHandler == null) {
// throw new IllegalStateException("Cannot grow");
// } else {
// id = this.resizeHandler.onResize(this.indexBits + 1, obj);
// }
// }
//
// return id;
// }
//
// private int addEntry(T obj) {
// int nextId = this.size;
//
// if (nextId >= this.entries.length) {
// this.resize(this.size);
// }
//
// this.table.put(obj, nextId);
// this.entries[nextId] = obj;
//
// this.size++;
//
// return nextId;
// }
//
// private void resize(int neededCapacity) {
// this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1));
// }
//
// @Override
// public T get(int id) {
// T[] entries = this.entries;
//
// T entry = null;
// if (id >= 0 && id < entries.length) {
// entry = entries[id];
// }
//
// if (entry != null) {
// return entry;
// } else {
// throw new EntryMissingException(id);
// }
// }
//
// @Override
// public void readPacket(PacketByteBuf buf) {
// this.clear();
//
// int entryCount = buf.readVarInt();
//
// for (int i = 0; i < entryCount; ++i) {
// this.addEntry(this.idList.get(buf.readVarInt()));
// }
// }
//
// @Override
// public void writePacket(PacketByteBuf buf) {
// int size = this.size;
// buf.writeVarInt(size);
//
// for (int i = 0; i < size; ++i) {
// buf.writeVarInt(this.idList.getRawId(this.get(i)));
// }
// }
//
// @Override
// public int getPacketSize() {
// int size = VarInts.getSizeInBytes(this.size);
//
// for (int i = 0; i < this.size; ++i) {
// size += VarInts.getSizeInBytes(this.idList.getRawId(this.get(i)));
// }
//
// return size;
// }
//
// @Override
// public int getSize() {
// return this.size;
// }
//
// @Override
// public Palette<T> copy() {
// return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size);
// }
//
// private void clear() {
// Arrays.fill(this.entries, null);
// this.table.clear();
// this.size = 0;
// }
//
// public List<T> getElements() {
// ImmutableList.Builder<T> builder = new ImmutableList.Builder<>();
// for (T entry : this.entries) {
// if (entry != null) {
// builder.add(entry);
// }
// }
// return builder.build();
// }
//
// public static <A> Palette<A> create(int bits, IndexedIterable<A> idList, PaletteResizeListener<A> listener, List<A> list) {
// return new LithiumHashPalette<>(idList, bits, listener, list);
// }
//}

View File

@@ -0,0 +1,36 @@
package net.gensokyoreimagined.nitori.mixin.collections.mob_spawning;
import com.google.common.collect.Maps;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.level.biome.MobSpawnSettings;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@Mixin(MobSpawnSettings.class)
public class SpawnSettingsMixin {
@Mutable
@Shadow
@Final
private Map<MobCategory, WeightedRandomList<MobSpawnSettings.SpawnerData>> spawners;
@Inject(method = "<init>(FLjava/util/Map;Ljava/util/Map;)V", at = @At("RETURN"))
private void reinit(float creatureSpawnProbability, Map<MobCategory, WeightedRandomList<MobSpawnSettings.SpawnerData>> spawners, Map<EntityType<?>, MobSpawnSettings.MobSpawnCost> spawnCosts, CallbackInfo ci) {
Map<MobCategory, WeightedRandomList<MobSpawnSettings.SpawnerData>> spawns = Maps.newEnumMap(MobCategory.class);
for (Map.Entry<MobCategory, WeightedRandomList<MobSpawnSettings.SpawnerData>> entry : this.spawners.entrySet()) {
spawns.put(entry.getKey(), entry.getValue());
}
this.spawners = spawns;
}
}

View File

@@ -0,0 +1,37 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.support_cache;
import net.gensokyoreimagined.nitori.common.world.blockentity.SupportCache;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.core.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(BlockEntity.class)
public abstract class BlockEntityMixin implements SupportCache {
@Shadow
public abstract BlockEntityType<?> getType();
@Unique
private boolean supportTestResult;
@Inject(method = "<init>(Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)V", at = @At("RETURN"))
private void initSupportCache(BlockEntityType<?> type, BlockPos pos, BlockState cachedState, CallbackInfo ci) {
this.supportTestResult = this.getType().isValid(cachedState);
}
@Inject(method = "setBlockState", at = @At("RETURN"))
private void updateSupportCache(BlockState cachedState, CallbackInfo ci) {
this.supportTestResult = this.getType().isValid(cachedState);
}
@Override
public boolean lithium$isSupported() {
return this.supportTestResult;
}
}

View File

@@ -0,0 +1,53 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.support_cache;
import net.gensokyoreimagined.nitori.common.world.blockentity.SupportCache;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;
@Mixin(targets = "net.minecraft.world.level.chunk.LevelChunk$BoundTickingBlockEntity")
public class DirectBlockEntityTickInvokerMixin<T extends BlockEntity> {
@Shadow
@Final
private T blockEntity;
@Redirect(
method = "tick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/chunk/LevelChunk;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;"
),
slice = @Slice(
from = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;push(Ljava/util/function/Supplier;)V"),
to = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/entity/BlockEntity;)V")
)
)
private BlockState getCachedState(LevelChunk chunk, BlockPos pos) {
return this.blockEntity.getBlockState();
}
@Redirect(
method = "tick()V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/entity/BlockEntityType;isValid(Lnet/minecraft/world/level/block/state/BlockState;)Z"
),
slice = @Slice(
from = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;push(Ljava/util/function/Supplier;)V"),
to = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/BlockEntityTicker;tick(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/entity/BlockEntity;)V")
)
)
private boolean cachedIsSupported(BlockEntityType<?> blockEntityType, BlockState block) {
return ((SupportCache) this.blockEntity).lithium$isSupported();
}
}

View File

@@ -0,0 +1,49 @@
package net.gensokyoreimagined.nitori.mixin.world.block_entity_ticking.support_cache;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.chunk.LevelChunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(LevelChunk.class)
public abstract class WorldChunkMixin {
@Shadow
public abstract BlockState getBlockState(BlockPos pos);
@Redirect(
method = "setBlockState(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;ZZ)Lnet/minecraft/world/level/block/state/BlockState;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/EntityBlock;newBlockEntity(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/minecraft/world/level/block/entity/BlockEntity;"
)
)
private BlockEntity createBlockEntityWithCachedStateFix(EntityBlock EntityBlock, BlockPos pos, BlockState state) {
return EntityBlock.newBlockEntity(pos, this.getBlockState(pos));
}
@Inject(
method = "setBlockState(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;ZZ)Lnet/minecraft/world/level/block/state/BlockState;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/entity/BlockEntity;setBlockState(Lnet/minecraft/world/level/block/state/BlockState;)V",
shift = At.Shift.AFTER
)
)
private void fixCachedState(BlockPos pos, BlockState state, boolean flag, boolean doPlace, CallbackInfoReturnable<BlockState> cir, @Local BlockEntity blockEntity) {
BlockState updatedBlockState = this.getBlockState(pos);
if (updatedBlockState != state) {
//noinspection deprecation
blockEntity.setBlockState(updatedBlockState);
}
}
}

View File

@@ -53,11 +53,15 @@
"collections.chunk_tickets.SortedArraySetMixin", "collections.chunk_tickets.SortedArraySetMixin",
"collections.block_entity_tickers.WorldChunkMixin", "collections.block_entity_tickers.WorldChunkMixin",
"collections.goals.GoalSelectorMixin", "collections.goals.GoalSelectorMixin",
"collections.mob_spawning.SpawnSettingsMixin",
"world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor", "world.block_entity_ticking.sleeping.WrappedBlockEntityTickInvokerAccessor",
"world.block_entity_ticking.sleeping.campfire.CampfireBlockEntityMixin", "world.block_entity_ticking.sleeping.campfire.CampfireBlockEntityMixin",
"world.block_entity_ticking.sleeping.campfire.unlit.CampfireBlockEntityMixin", "world.block_entity_ticking.sleeping.campfire.unlit.CampfireBlockEntityMixin",
"world.block_entity_ticking.sleeping.campfire.lit.CampfireBlockEntityMixin", "world.block_entity_ticking.sleeping.campfire.lit.CampfireBlockEntityMixin",
"world.block_entity_ticking.sleeping.furnace.AbstractFurnaceBlockEntityMixin", "world.block_entity_ticking.sleeping.furnace.AbstractFurnaceBlockEntityMixin",
"world.block_entity_ticking.support_cache.DirectBlockEntityTickInvokerMixin",
"world.block_entity_ticking.support_cache.BlockEntityMixin",
"world.block_entity_ticking.support_cache.WorldChunkMixin",
"util.accessors.ClientEntityManagerAccessor", "util.accessors.ClientEntityManagerAccessor",
"util.accessors.EntityTrackingSectionAccessor", "util.accessors.EntityTrackingSectionAccessor",
"util.accessors.ServerEntityManagerAccessor", "util.accessors.ServerEntityManagerAccessor",