package hunternif.mc.atlas.api.impl;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import hunternif.mc.atlas.AntiqueAtlasMod;
import hunternif.mc.atlas.api.TileAPI;
import hunternif.mc.atlas.client.BiomeTextureMap;
import hunternif.mc.atlas.client.TextureSet;
import hunternif.mc.atlas.client.TextureSetMap;
import hunternif.mc.atlas.core.AtlasData;
import hunternif.mc.atlas.core.Tile;
import hunternif.mc.atlas.ext.ExtBiomeData;
import hunternif.mc.atlas.ext.ExtTileIdMap;
import hunternif.mc.atlas.ext.ExtTileTextureMap;
import hunternif.mc.atlas.ext.TileIdRegisteredEvent;
import hunternif.mc.atlas.network.PacketDispatcher;
import hunternif.mc.atlas.network.bidirectional.PutBiomeTilePacket;
import hunternif.mc.atlas.network.client.DeleteCustomGlobalTilePacket;
import hunternif.mc.atlas.network.client.TileNameIDPacket;
import hunternif.mc.atlas.network.client.TilesPacket;
import hunternif.mc.atlas.network.server.RegisterTileIdPacket;
import hunternif.mc.atlas.util.Log;
public class TileApiImpl implements TileAPI {
/**
* When a tile is being put in an atlas on the client, the pseudo-biome ID
* may have been unregistered yet at that moment. In that case the tile data
* is put into this map to be later registered when the server sends the
* packet with the pseudo-biome ID for the corresponding unique name.
*/
private final Map<String, TileData> pendingTiles = new HashMap<>();
private static class TileData {
final World world;
final int atlasID, x, z;
TileData(World world, int atlasID, int x, int z) {
this.world = world;
this.atlasID = atlasID;
this.x = x;
this.z = z;
}
}
public TileApiImpl() {
MinecraftForge.EVENT_BUS.register(this);
}
@Override
public TextureSet registerTextureSet(String name, ResourceLocation... textures) {
TextureSet textureSet = new TextureSet(name, textures);
TextureSetMap.instance().register(textureSet);
return textureSet;
}
// Biome textures ==========================================================
@Override
public void setBiomeTexture(int biomeID, String textureSetName, ResourceLocation... textures) {
TextureSet set = new TextureSet(textureSetName, textures);
TextureSetMap.instance().register(set);
BiomeTextureMap.instance().setTexture(biomeID, set);
}
@Override
public void setBiomeTexture(Biome biome, String textureSetName, ResourceLocation... textures) {
setBiomeTexture(Biome.getIdForBiome(biome), textureSetName, textures);
}
@Override
public void setBiomeTexture(int biomeID, TextureSet textureSet) {
BiomeTextureMap.instance().setTexture(biomeID, textureSet);
}
@Override
public void setBiomeTexture(Biome biome, TextureSet textureSet) {
setBiomeTexture(Biome.getIdForBiome(biome), textureSet);
}
// Custom tile textures ====================================================
@Override
public void setCustomTileTexture(String uniqueTileName, ResourceLocation ... textures) {
TextureSet set = new TextureSet(uniqueTileName, textures);
TextureSetMap.instance().register(set);
setCustomTileTexture(uniqueTileName, set);
}
@Override
public void setCustomTileTexture(String uniqueTileName, TextureSet textureSet) {
ExtTileTextureMap.instance().setTexture(uniqueTileName, textureSet);
}
// Biome tiles =============================================================
@Override
public void putBiomeTile(World world, int atlasID, int biomeID, int chunkX, int chunkZ) {
int dimension = world.provider.getDimension();
PutBiomeTilePacket packet = new PutBiomeTilePacket(atlasID, dimension, chunkX, chunkZ, biomeID);
if (world.isRemote) {
PacketDispatcher.sendToServer(packet);
} else {
AtlasData data = AntiqueAtlasMod.atlasData.getAtlasData(atlasID, world);
Tile tile = new Tile(biomeID);
data.setTile(dimension, chunkX, chunkZ, tile);
for (EntityPlayer syncedPlayer : data.getSyncedPlayers()) {
PacketDispatcher.sendTo(new PutBiomeTilePacket(atlasID, dimension, chunkX, chunkZ, biomeID), (EntityPlayerMP)syncedPlayer);
}
}
}
@Override
public void putBiomeTile(World world, int atlasID, Biome biome, int chunkX, int chunkZ) {
putBiomeTile(world, atlasID, Biome.getIdForBiome(biome), chunkX, chunkZ);
}
// Custom tiles ============================================================
@Override
public void putCustomTile(World world, int atlasID, String tileName, int chunkX, int chunkZ) {
if (tileName == null) {
Log.error("Attempted to put custom tile with null name");
return;
}
if (world.isRemote) {
int biomeID = ExtTileIdMap.instance().getPseudoBiomeID(tileName);
if (biomeID != ExtTileIdMap.NOT_FOUND) {
putBiomeTile(world, atlasID, biomeID, chunkX, chunkZ);
} else {
pendingTiles.put(tileName, new TileData(world, atlasID, chunkX, chunkZ));
PacketDispatcher.sendToServer(new RegisterTileIdPacket(tileName));
}
} else {
int biomeID = ExtTileIdMap.instance().getPseudoBiomeID(tileName);
if (biomeID == ExtTileIdMap.NOT_FOUND) {
biomeID = ExtTileIdMap.instance().getOrCreatePseudoBiomeID(tileName);
TileNameIDPacket packet = new TileNameIDPacket();
packet.put(tileName, biomeID);
PacketDispatcher.sendToAll(packet);
}
putBiomeTile(world, atlasID, biomeID, chunkX, chunkZ);
}
}
@Override
public void putCustomGlobalTile(World world, String tileName, int chunkX, int chunkZ) {
if (tileName == null) {
Log.error("Attempted to put custom global tile with null name");
return;
}
if (world.isRemote) {
Log.warn("Client attempted to put global tile");
return;
}
boolean isIdRegistered = ExtTileIdMap.instance().getPseudoBiomeID(tileName) != ExtTileIdMap.NOT_FOUND;
int biomeID = ExtTileIdMap.instance().getOrCreatePseudoBiomeID(tileName);
ExtBiomeData data = AntiqueAtlasMod.extBiomeData.getData();
data.setBiomeIdAt(world.provider.getDimension(), chunkX, chunkZ, biomeID);
// Send name-ID packet:
if (!isIdRegistered) {
TileNameIDPacket packet = new TileNameIDPacket();
packet.put(tileName, biomeID);
PacketDispatcher.sendToAll(packet);
}
// Send tile packet:
TilesPacket packet = new TilesPacket(world.provider.getDimension());
packet.addTile(chunkX, chunkZ, biomeID);
PacketDispatcher.sendToAll(packet);
}
@SubscribeEvent
public void onTileIdRegistered(TileIdRegisteredEvent event) {
for (Entry<String, Integer> entry : event.nameToIdMap.entrySet()) {
// Put pending tiles:
TileData tile = pendingTiles.remove(entry.getKey());
if (tile != null) {
putBiomeTile(tile.world, tile.atlasID, entry.getValue(), tile.x, tile.z);
}
}
}
@Override
public void deleteCustomGlobalTile(World world, int chunkX, int chunkZ) {
if (world.isRemote) {
Log.warn("Client attempted to delete global tile");
return;
}
ExtBiomeData data = AntiqueAtlasMod.extBiomeData.getData();
int dimension = world.provider.getDimension();
if (data.getBiomeIdAt(dimension, chunkX, chunkZ) != -1) {
data.removeBiomeAt(dimension, chunkX, chunkZ);
PacketDispatcher.sendToAll(new DeleteCustomGlobalTilePacket(dimension, chunkX, chunkZ));
}
}
}