From a20e55beab2c2a5c47d289d9bd869a23be82ee48 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Fri, 9 Nov 2012 21:00:37 -0600 Subject: [PATCH] Add support for handling custom biomes (ExtraBiomes XL) --- .../java/org/dynmap/bukkit/DynmapPlugin.java | 59 +++++++++++++++++++ .../org/dynmap/bukkit/NewMapChunkCache.java | 43 ++++++++++++-- 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/dynmap/bukkit/DynmapPlugin.java b/src/main/java/org/dynmap/bukkit/DynmapPlugin.java index 742c1871..02a28e8b 100644 --- a/src/main/java/org/dynmap/bukkit/DynmapPlugin.java +++ b/src/main/java/org/dynmap/bukkit/DynmapPlugin.java @@ -2,6 +2,7 @@ package org.dynmap.bukkit; import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.InetSocketAddress; @@ -15,6 +16,8 @@ import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.Future; +import net.minecraft.server.BiomeBase; + import org.bukkit.ChatColor; import org.bukkit.Chunk; import org.bukkit.Location; @@ -622,6 +625,60 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { } } + public void loadExtraBiomes() { + Field tmpfld; + Field humfld; + int cnt = 0; + try { + tmpfld = BiomeBase.class.getField("temperature"); + } catch (NoSuchFieldException nsfx) { + try { + tmpfld = BiomeBase.class.getField("F"); + } catch (NoSuchFieldException nsfx2) { + Log.warning("BiomeBase.temperature field not found"); + tmpfld = null; + } + } + if((tmpfld != null) && (tmpfld.getType().getClass().isAssignableFrom(float.class) == false)) { + tmpfld = null; + } + try { + humfld = BiomeBase.class.getField("humidity"); + } catch (NoSuchFieldException nsfx) { + try { + humfld = BiomeBase.class.getField("G"); + } catch (NoSuchFieldException nsfx2) { + Log.warning("BiomeBase.humidity field not found"); + humfld = null; + } + } + if((humfld != null) && (humfld.getType().getClass().isAssignableFrom(float.class) == false)) { + humfld = null; + } + + for(int i = BiomeMap.LAST_WELL_KNOWN+1; i < BiomeBase.biomes.length; i++) { + BiomeBase bb = BiomeBase.biomes[i]; + if(bb != null) { + String id = "BIOME_" + i; + float tmp = 0.5F, hum = 0.5F; + try { + id = bb.y; + } catch (Exception x) {} + try { + if(tmpfld != null) + tmp = tmpfld.getFloat(bb); + if(humfld != null) + hum = humfld.getFloat(bb); + } catch (Exception x) { + } + BiomeMap m = new BiomeMap(i, id, tmp, hum); + Log.verboseinfo("Add custom biome [" + m.toString() + "] (" + i + ")"); + cnt++; + } + } + Log.info("Added " + cnt + " custom biome mappings"); + } + @Override public void onEnable() { pm = this.getServer().getPluginManager(); @@ -629,6 +686,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { PluginDescriptionFile pdfFile = this.getDescription(); version = pdfFile.getVersion(); + /* Load extra biomes, if any */ + loadExtraBiomes(); /* Set up player login/quit event handler */ registerPlayerLoginListener(); diff --git a/src/main/java/org/dynmap/bukkit/NewMapChunkCache.java b/src/main/java/org/dynmap/bukkit/NewMapChunkCache.java index 05f5821a..b92a7461 100644 --- a/src/main/java/org/dynmap/bukkit/NewMapChunkCache.java +++ b/src/main/java/org/dynmap/bukkit/NewMapChunkCache.java @@ -8,12 +8,14 @@ import java.util.Arrays; import java.util.List; import java.util.ListIterator; +import net.minecraft.server.BiomeBase; import net.minecraft.server.ChunkProviderServer; import org.bukkit.World; import org.bukkit.Chunk; import org.bukkit.block.Biome; import org.bukkit.craftbukkit.CraftChunk; +import org.bukkit.craftbukkit.CraftChunkSnapshot; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.util.LongHashset; import org.bukkit.ChunkSnapshot; @@ -35,6 +37,8 @@ public class NewMapChunkCache implements MapChunkCache { private static boolean use_spout = false; private static Field unloadqueue = null; private static Method queuecontainskey = null; + private static Field biomesnapshot = null; + private World w; private DynmapWorld dw; @@ -145,15 +149,37 @@ public class NewMapChunkCache implements MapChunkCache { sameneighborbiomecnt[i] = new byte[z_size]; biomemap[i] = new BiomeMap[z_size]; } + BiomeBase[] biomebase = null; + ChunkSnapshot biome_css = null; for(int i = 0; i < x_size; i++) { initialize(i + x_base, 64, z_base); for(int j = 0; j < z_size; j++) { - Biome bb = snap.getBiome(bx, bz); BiomeMap bm; - if(bb == null) - bm = BiomeMap.NULL; - else - bm = biome_to_bmap[bb.ordinal()]; + + if((biomesnapshot != null) && (snap != biome_css)) { + biomebase = null; + biome_css = snap; + try { + if (biome_css instanceof SpoutChunkSnapshot) { + biome_css = ((SpoutChunkSnapshot)biome_css).chunk; + } + if(biome_css instanceof CraftChunkSnapshot) { + biomebase = (BiomeBase[]) biomesnapshot.get(biome_css); + } + } catch (IllegalArgumentException iax) { + } catch (IllegalAccessException e) { + } + } + if(biomebase != null) { + bm = BiomeMap.byBiomeID(biomebase[bz << 4 | bx].id); + } + else { + Biome bb = snap.getBiome(bx, bz); + if(bb == null) + bm = BiomeMap.NULL; + else + bm = biome_to_bmap[bb.ordinal()]; + } biomemap[i][j] = bm; int cnt = 0; if(i > 0) { @@ -681,6 +707,13 @@ public class NewMapChunkCache implements MapChunkCache { } catch (NoSuchMethodException nsmx) { unloadqueue = null; } + try { + biomesnapshot = CraftChunkSnapshot.class.getDeclaredField("biome"); + biomesnapshot.setAccessible(true); + } catch (NoSuchFieldException nsfx) { + biomesnapshot = null; + Log.warning("Unable to find biome field in ChunkSnapshot"); + } init = true; } }