Jump to content

[1.7.10] Easy way to test a Chunk Provider?


yoshiquest

Recommended Posts

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

 

ლ(́◉◞౪◟◉‵ლ

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.