Posted December 22, 20159 yr Since I'm having to implement a Chunk Provider in a language other than Java (and a very different one at that), I'm having to rewrite its methods/functions from the ground up. It's going rather slowly, but I'm worried as to how I could test this once I'm done with it. I need to see if the generation provided by this is equal to vanilla, but I don't want to have to implement an entire new dimension to test it. Any ideas as to how I could test it once I (eventually) finish it? Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.
December 25, 20159 yr Author Ok, it's been 3 days and no one has answered, AND I've also just finished the implementation of the Chunk Provider, so I guess I'll rephrase my question. I'm wondering if there is possibly a way to replace Minecraft's world generation (perhaps in a different world type) with my Chunk Provider, keeping everything the same except for that. I'm just worried that since this implementation is HUGE (as is the original Minecraft provider), it'll break after I've already completed more advanced things later on, or not be accurate to Minecraft's current generator (which is what I'm trying to reimplement). So, does anyone know how to replace Minecraft's Chunk Provider with my own? Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.
December 26, 20159 yr Yes that is entirely possible. I currently use a version that allows me to have worlds with around 10 chunks each and no more than that. My chunk provider allows me to bypass world generation and create worlds that are empty by default. Using a bit of ASM you can add this to a World constructor: chunkProvider = new RegionChunkProvider(this); This is the code I use: (Note that I convert the chunkIntPair's into Integers and store them in a Hashset in the Ship class, those integers access the Chunks using a HashMap<Integer,Chunk>) package FlyingFortress.Region.WorldUtils; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.List; import net.minecraft.entity.EnumCreatureType; import net.minecraft.util.BlockPos; import net.minecraft.util.IProgressUpdate; import net.minecraft.world.MinecraftException; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.EmptyChunk; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.storage.AnvilChunkLoader; import FlyingFortress.Entities.Ship; import FlyingFortress.Region.ShipRegionServer; public class RegionChunkProvider implements IChunkProvider{ public EmptyChunk fakechunk; public HashMap<Integer,Chunk> hashToChunk = new HashMap<Integer,Chunk>(); public Ship parent; public World region; //Custom chunk storage System used by the Ship Regions public RegionChunkProvider(Ship ship,World worldIn){ parent = ship; region = worldIn; fakechunk = new EmptyChunk(region, 0, 0); for(int i:ship.chunksInUse){ IntegerChunkCoordIntPair pair = new IntegerChunkCoordIntPair(i); hashToChunk.put(i, new Chunk(region,pair.chunkXPos,pair.chunkZPos)); } } public void addChunk(int key){ IntegerChunkCoordIntPair pair = new IntegerChunkCoordIntPair(key); hashToChunk.put(key, new Chunk(region,pair.chunkXPos,pair.chunkZPos)); } public void removeChunk(int key){ hashToChunk.remove(key); IntegerChunkCoordIntPair pair = new IntegerChunkCoordIntPair(key); if(region instanceof ShipRegionServer){ AnvilChunkLoader loader = new AnvilChunkLoader(parent.getWorldDirectory()); try { loader.saveChunk(region, new EmptyChunk(region, pair.chunkXPos, pair.chunkZPos)); } catch (MinecraftException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public void setChunk(int key, Chunk chunk){ hashToChunk.remove(key); hashToChunk.put(key, chunk); } @Override public boolean chunkExists(int x, int z) { int hash = IntegerChunkCoordIntPair.toKey(x, z); return hashToChunk.containsKey(hash); } @Override public Chunk provideChunk(int x, int z) { int hash = IntegerChunkCoordIntPair.toKey(x, z); Chunk chunk; if(hashToChunk.containsKey(hash)){ chunk= hashToChunk.get(hash); }else{ chunk= fakechunk; } return chunk; } @Override public Chunk provideChunk(BlockPos blockPosIn) { return provideChunk(blockPosIn.getX() >> 4, blockPosIn.getZ() >> 4); } @Override public void populate(IChunkProvider p_73153_1_, int p_73153_2_,int p_73153_3_) {} @Override public boolean func_177460_a(IChunkProvider p_177460_1_, Chunk p_177460_2_, int p_177460_3_, int p_177460_4_) { return false; } @Override public boolean saveChunks(boolean p_73151_1_, IProgressUpdate p_73151_2_) { AnvilChunkLoader loader = new AnvilChunkLoader(parent.getWorldDirectory()); HashSet<Integer> chunksCopy = (HashSet<Integer>)parent.chunksInUse.clone(); HashMap<Integer,Chunk> hashToChunkCopy = (HashMap<Integer, Chunk>) hashToChunk.clone(); for(int i:chunksCopy){ Chunk chunk = hashToChunkCopy.get(i); try { loader.saveChunk(region, chunk); } catch (Exception e) { e.printStackTrace(); } } if(((ShipRegionServer)region).parent.isDead){ ((ShipRegionServer)region).parent.getWorldDirectory().delete(); } hashToChunkCopy.clear(); return true; } @Override public boolean unloadQueuedChunks() { return true; } //Set to false because I dont want this saving from both the Ship and the Region //Only the ship will make save requests @Override public boolean canSave() { return false; } @Override public String makeString() { return null; } @Override public List func_177458_a(EnumCreatureType p_177458_1_, BlockPos p_177458_2_) { return null; } @Override public BlockPos getStrongholdGen(World worldIn, String p_180513_2_,BlockPos p_180513_3_) { return null; } @Override public int getLoadedChunkCount() { return parent.chunksInUse.size(); } @Override public void recreateStructures(Chunk p_180514_1_, int p_180514_2_,int p_180514_3_) {} @Override public void saveExtraData() {} } My code isn't that important, but basically you could take direct control of what Minecraft receives as chunks as its coordinates. "you seem to be THE best modder I've seen imo." ~spynathan ლ(́◉◞౪◟◉‵ლ
December 27, 20159 yr Using WorldType is simpler than ASM: Create your class extending world type, as super constructor, use one with only string as argument. String is name of world type. There are a lot of usefull methods that you can override, one of them returning chunk provider. Now, in your main class, in init or pre init method, just do new YourWorldType() . It is also a good idea to store it somewhere, but if it is just for testing purposes, it may not be needed. Now, when creating new world, just seleсt your world type and you can test your generator. Check out my mods: BTAM Armor sets Avoid Exploding Creepers Tools compressor Anti Id Conflict Key bindings overhaul Colourfull blocks Invisi Zones
December 28, 20159 yr Author Using WorldType is simpler than ASM: Create your class extending world type, as super constructor, use one with only string as argument. String is name of world type. There are a lot of usefull methods that you can override, one of them returning chunk provider. Now, in your main class, in init or pre init method, just do new YourWorldType() . It is also a good idea to store it somewhere, but if it is just for testing purposes, it may not be needed. Now, when creating new world, just seleсt your world type and you can test your generator. Thank you. This is EXACTLY what I needed. Might not do it exactly the same way (this is Clojure, not Java, after all), but with this I should be able to test it easily enough. Again, thanks. Currently working on a mod to provide support for the Clojure programming language in Minecraft, check it out here.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.