-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Backport Aversion Obelisk and Soul Filters
Thanks a lot to krxdev-kaan for backporting these features!
- Loading branch information
1 parent
d26fb4c
commit 75bb8b2
Showing
41 changed files
with
1,493 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.enderio.api.filter; | ||
|
||
import net.minecraft.world.entity.Entity; | ||
import net.minecraft.world.entity.EntityType; | ||
|
||
import java.util.function.Predicate; | ||
|
||
public interface EntityFilter extends ResourceFilter, Predicate<Entity> { | ||
|
||
boolean test(EntityType<?> entity); | ||
} |
141 changes: 141 additions & 0 deletions
141
src/core/java/com/enderio/core/common/capability/EntityFilterCapability.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package com.enderio.core.common.capability; | ||
|
||
import com.enderio.api.capability.StoredEntityData; | ||
import com.enderio.api.filter.EntityFilter; | ||
import net.minecraft.core.registries.BuiltInRegistries; | ||
import net.minecraft.nbt.CompoundTag; | ||
import net.minecraft.nbt.ListTag; | ||
import net.minecraft.resources.ResourceLocation; | ||
import net.minecraft.world.entity.Entity; | ||
import net.minecraft.world.entity.EntityType; | ||
import net.minecraft.world.item.ItemStack; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class EntityFilterCapability implements IFilterCapability<StoredEntityData>, EntityFilter { | ||
|
||
private static final String NBT_KEY = "IsNbt"; | ||
private static final String INVERTED_KEY = "IsInverted"; | ||
private static final String ENTRIES_KEY = "EntityEntries"; | ||
|
||
private final ItemStack container; | ||
private final int size; | ||
|
||
public EntityFilterCapability(ItemStack container, int size) { | ||
this.container = container; | ||
this.size = size; | ||
|
||
CompoundTag tag = container.getOrCreateTag(); | ||
if (!tag.contains(ENTRIES_KEY, CompoundTag.TAG_LIST)) { | ||
ListTag entriesList = new ListTag(); | ||
for (int i = 0; i < size; i++) { | ||
entriesList.add(StoredEntityData.empty().serializeNBT()); | ||
} | ||
tag.put(ENTRIES_KEY, entriesList); | ||
} | ||
} | ||
|
||
@Override | ||
public void setNbt(Boolean nbt) { | ||
CompoundTag tag = container.getOrCreateTag(); | ||
tag.putBoolean(NBT_KEY, nbt); | ||
} | ||
|
||
@Override | ||
public boolean isNbt() { | ||
CompoundTag tag = container.getOrCreateTag(); | ||
return tag.contains(NBT_KEY, CompoundTag.TAG_BYTE) && tag.getBoolean(NBT_KEY); | ||
} | ||
|
||
@Override | ||
public void setInverted(Boolean inverted) { | ||
CompoundTag tag = container.getOrCreateTag(); | ||
tag.putBoolean(INVERTED_KEY, inverted); | ||
} | ||
|
||
@Override | ||
public boolean isInvert() { | ||
CompoundTag tag = container.getOrCreateTag(); | ||
return tag.contains(INVERTED_KEY, CompoundTag.TAG_BYTE) && tag.getBoolean(INVERTED_KEY); | ||
} | ||
|
||
@Override | ||
public int size() { | ||
return size; | ||
} | ||
|
||
@Override | ||
public List<StoredEntityData> getEntries() { | ||
CompoundTag tag = container.getOrCreateTag(); | ||
|
||
List<StoredEntityData> entries = new ArrayList<>(); | ||
if (tag.contains(ENTRIES_KEY, CompoundTag.TAG_LIST)) { | ||
ListTag entriesList = tag.getList(ENTRIES_KEY, CompoundTag.TAG_COMPOUND); | ||
for (var entry : entriesList) { | ||
StoredEntityData entityData = StoredEntityData.empty(); | ||
entityData.deserializeNBT(entry); | ||
entries.add(entityData); | ||
} | ||
} | ||
|
||
return entries; | ||
} | ||
|
||
@Override | ||
public StoredEntityData getEntry(int index) { | ||
CompoundTag tag = container.getOrCreateTag(); | ||
|
||
if (!tag.contains(ENTRIES_KEY, CompoundTag.TAG_LIST)) { | ||
return StoredEntityData.empty(); | ||
} | ||
|
||
ListTag entriesList = tag.getList(ENTRIES_KEY, CompoundTag.TAG_COMPOUND); | ||
StoredEntityData entityData = StoredEntityData.empty(); | ||
entityData.deserializeNBT(entriesList.get(index)); | ||
return entityData; | ||
} | ||
|
||
@Override | ||
public void setEntry(int index, StoredEntityData entry) { | ||
CompoundTag tag = container.getOrCreateTag(); | ||
|
||
ListTag entriesList; | ||
if (tag.contains(ENTRIES_KEY, CompoundTag.TAG_LIST)) { | ||
entriesList = tag.getList(ENTRIES_KEY, CompoundTag.TAG_COMPOUND); | ||
} else { | ||
entriesList = new ListTag(); | ||
tag.put(ENTRIES_KEY, entriesList); | ||
} | ||
|
||
entriesList.set(index, entry.serializeNBT()); | ||
} | ||
|
||
@Override | ||
public boolean test(Entity entity) { | ||
boolean typematch = test(entity.getType()); | ||
if (isNbt()) { | ||
for (StoredEntityData entry : getEntries()) { | ||
CompoundTag tag = entity.serializeNBT(); | ||
boolean test = tag.equals(entry.getEntityTag()); | ||
if (test) { | ||
return !isInvert() && typematch; | ||
} | ||
} | ||
} | ||
|
||
return typematch; | ||
} | ||
|
||
@Override | ||
public boolean test(EntityType<?> entity) { | ||
for (StoredEntityData entry : getEntries()) { | ||
ResourceLocation key = BuiltInRegistries.ENTITY_TYPE.getKey(entity); | ||
if (entry.getEntityType().isPresent() && entry.getEntityType().get().equals(key)) { | ||
return !isInvert(); | ||
} | ||
} | ||
return isInvert(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
164 changes: 164 additions & 0 deletions
164
src/core/java/com/enderio/core/common/util/ChunkBoundLookup.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
package com.enderio.core.common.util; | ||
|
||
import com.google.common.collect.Sets; | ||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; | ||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; | ||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; | ||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; | ||
import net.minecraft.core.BlockPos; | ||
import net.minecraft.world.level.ChunkPos; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
/** | ||
* Implements the concept of a spatial hashmap, bucketed by chunk. | ||
*/ | ||
public class ChunkBoundLookup<T> { | ||
private final Long2ObjectMap<Set<T>> chunkData = new Long2ObjectOpenHashMap<>(); | ||
private final Reference2ObjectMap<T, Set<ChunkPos>> valueKeys = new Reference2ObjectOpenHashMap<>(); | ||
|
||
@Nullable | ||
public Set<T> getForChunk(ChunkPos pos) { | ||
return chunkData.get(pos.toLong()); | ||
} | ||
|
||
// region Direct Chunk Manipulation | ||
|
||
/** | ||
* Adds a value to a chunk in the lookup. | ||
* | ||
* @param pos The chunk to be added to. | ||
* @param value The value to add. | ||
*/ | ||
public void addToChunk(ChunkPos pos, T value) { | ||
chunkData.computeIfAbsent(pos.toLong(), k -> new HashSet<>()).add(value); | ||
valueKeys.computeIfAbsent(value, k -> new HashSet<>()).add(pos); | ||
} | ||
|
||
/** | ||
* Remove a value from a chunk in the lookup. | ||
* | ||
* @param pos The chunk to be removed from. | ||
* @param value The value to remove. | ||
*/ | ||
public void removeFromChunk(ChunkPos pos, T value) { | ||
if (chunkData.containsKey(pos.toLong())) { | ||
chunkData.get(pos.toLong()).remove(value); | ||
} | ||
|
||
if (valueKeys.containsKey(value)) { | ||
valueKeys.get(value).remove(pos); | ||
} | ||
} | ||
|
||
// endregion | ||
|
||
// region Chunk and Block Ranges | ||
|
||
/** | ||
* Add the given value to the lookup with the given center point and square radius. | ||
* | ||
* @param centerPos The center block position of the range. | ||
* @param blockRadius The radius (in blocks) of the range. | ||
* @param value The value to add. | ||
*/ | ||
public void addForBlockRadius(BlockPos centerPos, int blockRadius, T value) { | ||
getBlockRadius(centerPos, blockRadius).forEach(chunkPos -> addToChunk(chunkPos, value)); | ||
} | ||
|
||
/** | ||
* Update the center position and radius of an existing entry efficiently. | ||
* Instead of removing from all chunks then adding to all chunks, this only adds and removes the differences. | ||
* If the item does not yet exist, behaves the same as addForBlockRadius. | ||
* | ||
* @param centerPos The center block position of the range. | ||
* @param blockRadius The radius (in blocks) of the range. | ||
* @param value The value to update. | ||
*/ | ||
public void updateForBlockRadius(BlockPos centerPos, int blockRadius, T value) { | ||
Set<ChunkPos> currentChunks = valueKeys.get(value); | ||
if (currentChunks == null) { | ||
addForBlockRadius(centerPos, blockRadius, value); | ||
return; | ||
} | ||
|
||
Set<ChunkPos> newChunks = getBlockRadius(centerPos, blockRadius).collect(Collectors.toSet()); | ||
bulkUpdate(value, currentChunks, newChunks); | ||
} | ||
|
||
/** | ||
* Add the given value to the lookup with the given center point and square radius. | ||
* | ||
* @param centerPos The center chunk position of the range. | ||
* @param chunkRadius The radius (in chunks) of the range. | ||
* @param value The value to add. | ||
*/ | ||
public void addForChunkRadius(ChunkPos centerPos, int chunkRadius, T value) { | ||
ChunkPos.rangeClosed(centerPos, chunkRadius).forEach(chunkPos -> addToChunk(chunkPos, value)); | ||
} | ||
|
||
/** | ||
* Update the center position and radius of an existing entry efficiently. | ||
* Instead of removing from all chunks then adding to all chunks, this only adds and removes the differences. | ||
* If the item does not yet exist, behaves the same as addForBlockRadius. | ||
* | ||
* @param centerPos The center chunk position of the range. | ||
* @param chunkRadius The radius (in chunks) of the range. | ||
* @param value The value to update. | ||
*/ | ||
public void updateForChunkRadius(ChunkPos centerPos, int chunkRadius, T value) { | ||
Set<ChunkPos> currentChunks = valueKeys.get(value); | ||
if (currentChunks == null) { | ||
addForChunkRadius(centerPos, chunkRadius, value); | ||
return; | ||
} | ||
|
||
Set<ChunkPos> newChunks = ChunkPos.rangeClosed(centerPos, chunkRadius).collect(Collectors.toSet()); | ||
bulkUpdate(value, currentChunks, newChunks); | ||
} | ||
|
||
private Stream<ChunkPos> getBlockRadius(BlockPos centerPos, int blockRadius) { | ||
BlockPos startBlockPos = new BlockPos(centerPos.getX() - blockRadius, 0, centerPos.getZ() - blockRadius); | ||
BlockPos endBlockPos = new BlockPos(centerPos.getX() + blockRadius, 0, centerPos.getZ() + blockRadius); | ||
|
||
ChunkPos startChunkPos = new ChunkPos(startBlockPos); | ||
ChunkPos endChunkPos = new ChunkPos(endBlockPos); | ||
|
||
return ChunkPos.rangeClosed(startChunkPos, endChunkPos); | ||
} | ||
|
||
private void bulkUpdate(T value, Set<ChunkPos> chunksBefore, Set<ChunkPos> chunksAfter) { | ||
Sets.SetView<ChunkPos> removedChunks = Sets.difference(chunksBefore, chunksAfter); | ||
Sets.SetView<ChunkPos> addedChunks = Sets.difference(chunksAfter, chunksBefore); | ||
|
||
removedChunks.forEach(chunkPos -> removeFromChunk(chunkPos, value)); | ||
addedChunks.forEach(chunkPos -> addToChunk(chunkPos, value)); | ||
} | ||
|
||
// endregion | ||
|
||
/** | ||
* Remove all instances of this value from the lookup. | ||
* | ||
* @param value The value to remove. | ||
*/ | ||
public void remove(T value) { | ||
Set<ChunkPos> chunks = valueKeys.get(value); | ||
for (ChunkPos chunkPos : chunks) { | ||
Set<T> dataAtChunk = chunkData.get(chunkPos.toLong()); | ||
|
||
if (dataAtChunk != null) { | ||
dataAtChunk.remove(value); | ||
if (dataAtChunk.isEmpty()) { | ||
chunkData.remove(chunkPos.toLong()); | ||
} | ||
} | ||
} | ||
|
||
valueKeys.remove(value); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/generated/resources/assets/enderio/blockstates/aversion_obelisk.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"variants": { | ||
"": { | ||
"model": "enderio:block/aversion_obelisk" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
src/generated/resources/assets/enderio/models/item/aversion_obelisk.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"parent": "enderio:block/aversion_obelisk" | ||
} |
6 changes: 6 additions & 0 deletions
6
src/generated/resources/assets/enderio/models/item/entity_filter.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"parent": "minecraft:item/generated", | ||
"textures": { | ||
"layer0": "enderio:item/entity_filter" | ||
} | ||
} |
Oops, something went wrong.