forked from TheBrokenRail/EnergonRelics
191 lines
6.5 KiB
Java
191 lines
6.5 KiB
Java
package com.thebrokenrail.energonrelics.component;
|
|
|
|
import com.thebrokenrail.energonrelics.EnergonRelics;
|
|
import com.thebrokenrail.energonrelics.energy.core.EnergyProviderBlockEntity;
|
|
import com.thebrokenrail.energonrelics.util.BlockPosWithDimension;
|
|
import net.minecraft.block.entity.BlockEntity;
|
|
import net.minecraft.datafixer.NbtOps;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.nbt.ListTag;
|
|
import net.minecraft.nbt.Tag;
|
|
import net.minecraft.server.world.ServerWorld;
|
|
import net.minecraft.util.Identifier;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.registry.RegistryKey;
|
|
import net.minecraft.world.PersistentState;
|
|
import net.minecraft.world.World;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
|
|
public class NetworkComponent extends PersistentState {
|
|
private static class Entry {
|
|
private final List<BlockPosWithDimension> sources = new ArrayList<>();
|
|
private int id = 0;
|
|
}
|
|
|
|
private final List<Entry> networks = new ArrayList<>();
|
|
|
|
private NetworkComponent() {
|
|
super(EnergonRelics.NAMESPACE);
|
|
}
|
|
|
|
@Override
|
|
public void fromTag(CompoundTag tag) {
|
|
networks.clear();
|
|
Tag list = tag.get("Networks");
|
|
if (list instanceof ListTag) {
|
|
ListTag networksTag = (ListTag) list;
|
|
for (int i = 0; i < networksTag.size(); i++) {
|
|
networks.add(getEntry(networksTag.getCompound(i)));
|
|
}
|
|
}
|
|
}
|
|
|
|
private Entry getEntry(CompoundTag tag) {
|
|
Entry entry = new Entry();
|
|
entry.id = tag.getInt("ID");
|
|
entry.sources.clear();
|
|
Tag list = tag.get("Sources");
|
|
if (list instanceof ListTag) {
|
|
ListTag sources = (ListTag) list;
|
|
for (int i = 0; i < sources.size(); i++) {
|
|
int x = sources.getCompound(i).getInt("X");
|
|
int y = sources.getCompound(i).getInt("Y");
|
|
int z = sources.getCompound(i).getInt("Z");
|
|
RegistryKey<World> dimension = World.CODEC.parse(NbtOps.INSTANCE, sources.getCompound(i).get("Dimension")).result().orElse(World.OVERWORLD);
|
|
entry.sources.add(new BlockPosWithDimension(new BlockPos(x, y, z), dimension));
|
|
}
|
|
}
|
|
return entry;
|
|
}
|
|
|
|
private CompoundTag saveEntry(Entry entry) {
|
|
CompoundTag tag = new CompoundTag();
|
|
tag.putInt("ID", entry.id);
|
|
ListTag sources = new ListTag();
|
|
for (BlockPosWithDimension pos : entry.sources) {
|
|
CompoundTag posTag = new CompoundTag();
|
|
posTag.putInt("X", pos.pos.getX());
|
|
posTag.putInt("Y", pos.pos.getY());
|
|
posTag.putInt("Z", pos.pos.getZ());
|
|
Identifier.CODEC.encodeStart(NbtOps.INSTANCE, pos.dimension.getValue()).result().ifPresent(tags -> posTag.put("Dimension", tags));
|
|
sources.add(posTag);
|
|
}
|
|
tag.put("Sources", sources);
|
|
return tag;
|
|
}
|
|
|
|
@Override
|
|
public CompoundTag toTag(CompoundTag tag) {
|
|
ListTag networksTag = new ListTag();
|
|
for (Entry entry : networks) {
|
|
networksTag.add(saveEntry(entry));
|
|
}
|
|
tag.put("Networks", networksTag);
|
|
return tag;
|
|
}
|
|
|
|
private Entry getOrCreate(int id) {
|
|
markDirty();
|
|
for (Entry entry : networks) {
|
|
if (entry.id == id) {
|
|
return entry;
|
|
}
|
|
}
|
|
Entry entry = new Entry();
|
|
entry.id = id;
|
|
entry.sources.clear();
|
|
networks.add(entry);
|
|
return entry;
|
|
}
|
|
|
|
public static NetworkComponent getInstance(ServerWorld world) {
|
|
return Objects.requireNonNull(world.getServer().getWorld(World.OVERWORLD)).getPersistentStateManager().getOrCreate(NetworkComponent::new, EnergonRelics.NAMESPACE);
|
|
}
|
|
|
|
public List<BlockPosWithDimension> getSourcePos(int id) {
|
|
Entry entry = getOrCreate(id);
|
|
return entry.sources;
|
|
}
|
|
|
|
public List<EnergyProviderBlockEntity> getSource(World world, int id) {
|
|
List<BlockPosWithDimension> sources = getSourcePos(id);
|
|
List<BlockPosWithDimension> valid = new ArrayList<>();
|
|
Iterator<BlockPosWithDimension> iterator = sources.iterator();
|
|
List<EnergyProviderBlockEntity> providers = new ArrayList<>();
|
|
boolean dirty = false;
|
|
while (iterator.hasNext()) {
|
|
BlockPosWithDimension pos = iterator.next();
|
|
if (!valid.contains(pos)) {
|
|
BlockEntity entity = Objects.requireNonNull(Objects.requireNonNull(world.getServer()).getWorld(pos.dimension)).getBlockEntity(pos.pos);
|
|
if (entity instanceof EnergyProviderBlockEntity && ((EnergyProviderBlockEntity) entity).isNetwork(id)) {
|
|
providers.add((EnergyProviderBlockEntity) entity);
|
|
} else {
|
|
iterator.remove();
|
|
dirty = true;
|
|
}
|
|
valid.add(pos);
|
|
} else {
|
|
iterator.remove();
|
|
dirty = true;
|
|
}
|
|
}
|
|
if (dirty) {
|
|
markDirty();
|
|
}
|
|
Collections.shuffle(providers);
|
|
return providers;
|
|
}
|
|
|
|
public void addSource(int id, BlockPosWithDimension pos) {
|
|
Entry entry = getOrCreate(id);
|
|
if (!entry.sources.contains(pos)) {
|
|
entry.sources.add(pos);
|
|
}
|
|
markDirty();
|
|
}
|
|
|
|
public void removeSource(int id, BlockPosWithDimension pos) {
|
|
Entry entry = getOrCreate(id);
|
|
entry.sources.remove(pos);
|
|
markDirty();
|
|
}
|
|
|
|
public int create() {
|
|
int id = -1;
|
|
for (Entry entry : networks) {
|
|
id = Math.max(id, entry.id);
|
|
}
|
|
return getOrCreate(id + 1).id;
|
|
}
|
|
|
|
@Override
|
|
public void markDirty() {
|
|
List<Integer> ids = new ArrayList<>();
|
|
List<BlockPosWithDimension> positions = new ArrayList<>();
|
|
Iterator<Entry> iterator = networks.iterator();
|
|
while (iterator.hasNext()) {
|
|
Entry entry = iterator.next();
|
|
boolean remove = false;
|
|
if (ids.contains(entry.id)) {
|
|
remove = true;
|
|
} else {
|
|
ids.add(entry.id);
|
|
}
|
|
if (!Collections.disjoint(positions, entry.sources)) {
|
|
remove = true;
|
|
} else {
|
|
positions.addAll(entry.sources);
|
|
}
|
|
if (remove) {
|
|
iterator.remove();
|
|
}
|
|
}
|
|
super.markDirty();
|
|
}
|
|
}
|