package hunternif.mc.atlas.ext;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.minecraftforge.event.terraingen.PopulateChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.MapGenStructureData;
import hunternif.mc.atlas.AntiqueAtlasMod;
import hunternif.mc.atlas.api.AtlasAPI;
import hunternif.mc.atlas.marker.Marker;
import hunternif.mc.atlas.marker.MarkersData;
import hunternif.mc.atlas.registry.MarkerType;
import hunternif.mc.atlas.util.Log;
public class StructureWatcher {
private final String datFileName;
private MarkerType marker;
private MarkerType tileMarker;
private String markerLabel;
private String tileMarkerLabel;
private final int dim;
public StructureWatcher(String datFileName, int dim, MarkerType marker, String label) {
this.marker = marker;
markerLabel = label;
this.dim = dim;
this.datFileName = datFileName;
}
public StructureWatcher setTileMarker(MarkerType type, String label) {
tileMarker = type;
tileMarkerLabel = label;
return this;
}
/** Set of tag names for every structure, in the format "[x, y]" */
//TODO: list of visited structures(?) must be reset when changing worlds!
private final Set<String> visited = new HashSet<>();
@SubscribeEvent(priority=EventPriority.LOWEST)
public void onWorldLoad(WorldEvent.Load event) {
if (!event.getWorld().isRemote && event.getWorld().provider.getDimension() == dim) {
visitAllUnvisitedStructures(event.getWorld());
}
}
@SubscribeEvent
public void onPopulateChunk(PopulateChunkEvent.Post event) {
if (!event.getWorld().isRemote && event.getWorld().provider.getDimension() == dim) {
visitAllUnvisitedStructures(event.getWorld());
}
}
private void visitAllUnvisitedStructures(World world) {
MapGenStructureData data = (MapGenStructureData)world.getPerWorldStorage().getOrLoadData(MapGenStructureData.class, datFileName);
if (data == null) return;
NBTTagCompound nbtData = data.getTagCompound();
Set<String> tagSet = nbtData.getKeySet();
for (String coords : tagSet) {
if (!visited.contains(coords)) {
NBTBase tag = nbtData.getTag(coords);
if (tag.getId() == 10) { // is NBTTagCompound
visitStructure(world, (NBTTagCompound) tag);
visited.add(coords);
}
}
}
}
private void visitStructure(World world, NBTTagCompound tag) {
int chunkX = tag.getInteger("ChunkX");
int chunkZ = tag.getInteger("ChunkZ");
Log.info(" Visiting " + datFileName + " in dimension #%d \"%s\" at chunk (%d, %d) ~ blocks (%d, %d)",
world.provider.getDimension(), world.provider.getDimensionType().getName(),
chunkX, chunkZ, chunkX << 4, chunkZ << 4);
boolean foundMarker = false;
boolean foundTileMarker = false;
List<Marker> markers = AntiqueAtlasMod.globalMarkersData.getData()
.getMarkersAtChunk(world.provider.getDimension(), chunkX / MarkersData.CHUNK_STEP, chunkZ / MarkersData.CHUNK_STEP);
if (markers != null) {
for (Marker marker : markers) {
if (!foundMarker && marker.getChunkX() == chunkX && marker.getChunkZ() == chunkZ &&
marker.getType().equals(this.marker)) {
foundMarker = true;
}
if (!foundTileMarker && tileMarker != null && marker.getChunkX() == chunkX && marker.getChunkZ() == chunkZ &&
marker.getType().equals(tileMarker)) {
foundTileMarker = true;
}
}
}
if (AntiqueAtlasMod.settings.autoVillageMarkers) {
if(!foundMarker)
AtlasAPI.markers.putGlobalMarker(world, false, marker, markerLabel, (chunkX << 4) + 8, (chunkZ << 4) + 8);
if(tileMarker != null && !foundTileMarker)
AtlasAPI.markers.putGlobalMarker(world, false, tileMarker, tileMarkerLabel, (chunkX << 4) + 8, (chunkZ << 4) + 8);
}
}
private void clearAllMarkers(World world) {
Collection<Marker> markers = AntiqueAtlasMod.globalMarkersData.getData().getMarkersInDimension(world.provider.getDimension());
for (Marker marker : markers) {
if(marker.getType().equals(this.marker)) {
AtlasAPI.markers.deleteGlobalMarker(world, marker.getId());
}
if(tileMarker != null && marker.getType().equals(tileMarker)) {
AtlasAPI.markers.deleteGlobalMarker(world, marker.getId());
}
}
}
}