Jump to content

Recommended Posts

Posted

Hello modders,

I need help with my mod. Can you read schematic files and generate them randomly in the world without converting schematic to java code ? Maybe it is good to  read the schematic file into bytes and then set arrays or HashMaps ? Or best with inputStream? And how would you do it ? If you have an idea and a code for the beginning please help me. Thank you.

Posted

public Schematic get(String schemname){
        try {
            InputStream is = this.getClass().getClassLoader().getResourceAsStream("assets/mymod/schem/"+schemname);
            NBTTagCompound nbtdata = CompressedStreamTools.readCompressed(is);
            short width = nbtdata.getShort("Width");
            short height = nbtdata.getShort("Height");
            short length = nbtdata.getShort("Length");

            byte[] blocks = nbtdata.getByteArray("Blocks");
            byte[] data = nbtdata.getByteArray("Data");


            System.out.println("schem size:" + width + " x " + height + " x " + length);
            NBTTagList tileentities = nbtdata.getTagList("TileEntities", 10);
            is.close();

            return new Schematic(tileentities, width, height, length, blocks, data);
        } catch (Exception e) {
            System.out.println("I can't load schematic, because " + e.toString());
            return null;
        }
    }

    public class Schematic{
        public  NBTTagList tileentities;
        public  short width;
        public  short height;
        public short length;
        public byte[] blocks;
        public byte[] data;
        public Schematic(NBTTagList tileentities, short width, short height, short length, byte[] blocks, byte[] data){
            this.tileentities = tileentities;
            this.width = width;
            this.height = height;
            this.length = length;
            this.blocks = blocks;
            this.data = data;
        }

    }

 

And it's from my item code, maybe it can help you:

public boolean onItemUse(ItemStack is, EntityPlayer placer, World world, int x, int y, int z, int side, float px, float py, float pz) {

        if(!world.isRemote && !blocked && delay<=0 && side == 1 && placer.capabilities.isCreativeMode){
        blocked = true;
        delay = 20;
        int rotation = OtherUtils.getPlayerRotationSide(placer);
        SchemUtils.Schematic sh = sut.get(schematic);
        if(sh==null){
            placer.addChatMessage(new ChatComponentText("Schematic is dead!"));
            this.setUnlocalizedName("builder_corrupt");
        return false;}

       if(logBuilding)placer.addChatMessage(new ChatComponentText("Building started."));

        int i = 0;
        for(int sy = 0; sy < sh.height; sy++)
        for(int sz = 0; sz < sh.length; sz++)
        for(int sx = 0; sx < sh.width; sx++){

                Block b = Block.getBlockById(sh.blocks[i]);
                if(b!= Blocks.air)
                {
                    int rx = SchemUtils.blockCoordsRotation(sx - this.getxShift(), sz, rotation)[0];
                    int rz = SchemUtils.blockCoordsRotation(sx - this.getxShift(), sz, rotation)[1];
                    world.setBlockToAir(x + rx, y + ylevel + sy, z + rz);
                    world.setBlock(x+rx, y+ylevel+sy, z+rz, b, SchemUtils.rotateMeta(sh.blocks[i], sh.data[i], rotation ), 2);
                }
                i++;
        }

        if (sh.tileentities != null)
        {
            for (int i1 = 0; i1 < sh.tileentities.tagCount(); ++i1)
            {
                NBTTagCompound nbttagcompound4 = sh.tileentities.getCompoundTagAt(i1);
                TileEntity tileentity = TileEntity.createAndLoadEntity(nbttagcompound4);

                if (tileentity != null)
                {
                    int[] conv2 = SchemUtils.blockCoordsRotation(tileentity.xCoord - this.getxShift(), tileentity.zCoord, rotation);
                    tileentity.xCoord = x + conv2[0];
                    tileentity.yCoord += y+ylevel;
                    tileentity.zCoord = z + conv2[1];
                    world.setTileEntity(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord, tileentity);
                }
            }
        }

       if(logBuilding) placer.addChatMessage(new ChatComponentText("Building finished."));
        blocked = false;
        return true;
        }
        return false;
    }

Posted

So this would be right in the WorldGenerate method:

for(int chanceForChuk = 0; chanceForChuk < 1; chanceForChuk++) {
        	Schematic spring = SchematicLoader.get("spring");
        	 int i = 0;
             for(int cy = 0; cy < spring.height; cy++)
             for(int cz = 0; cz < spring.length; cz++)
             for(int cx = 0; cx < spring.width; cx++){

                     Block b = Block.getBlockById(spring.blocks[i]);
                     if(b!= Blocks.air)
                     {
                         world.setBlockToAir(cx , cy, cz);
                         world.setBlock(cx, cy, cz, b, Integer.parseInt(String.valueOf(spring.data[i])), 2);
                     }
                     i++;
             }
        }

Or would it be other if cx, cy, cz are my coordinates ? I am new with structure spawning in the world... Thanks for your help

Posted

Oh, forget my code, i just write before I test. I read your code carefully but because of your rotationthings i am not sure about it, so how do you can generate a structure with the Schematic and blocks[] and data[] ?

 

I used Integer.parseINt(String.valueOf(spring.data)); because i needed an integer and Integer.something returns an integer, but i didn´t saw a byte - convert, so i tried to make first a string from the data stored in data and then I tried to get the value of this string.. Very complicated..

Posted

Your code is correct. And you can pass meta directly, byte normally casts to int (world.setBlock(cx, cy, cz, b, spring.data[і]), 2); ).

 

And another thing.

Schematic spring = SchematicLoader.get("spring");

Don't forget to add extention to filename if you didnt do it.

Posted

I get an error:

 

my WorldGen code:

package de.MhytRPG.www.worldgen;

import java.util.Random;

import cpw.mods.fml.common.IWorldGenerator;
import de.MhytRPG.www.MhytRPG;
import de.MhytRPG.www.structures.Schematic;
import de.MhytRPG.www.structures.SchematicLoader;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.feature.WorldGenLiquids;
import net.minecraft.world.gen.feature.WorldGenMinable;
import net.minecraft.world.gen.feature.WorldGenerator;

public class WorldGen implements IWorldGenerator{

@Override
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) {
        switch(world.provider.dimensionId){
        case -1:
            generateNether(world, random, chunkX * 16, chunkZ * 16);
            break;
        case 0:
            generateSurface(world, random, chunkX * 16, chunkZ * 16);
            break;
        case 1:
            generateEnd(world, random, chunkX * 16, chunkZ * 16);
            break;
        }
}

private void generateEnd(World world, Random rand, int chunkX, int chunkZ) {}

private void generateSurface(World world, Random rand, int chunkX, int chunkZ) {
        for(int k = 0; k < 10; k++){
        	int firstBlockXCoord = chunkX + rand.nextInt(16);
        	int firstBlockYCoord = rand.nextInt(200);
        	int firstBlockZCoord = chunkZ + rand.nextInt(16);
        	
        	(new WorldGenLiquids(MhytRPG.blockgoldenwater)).generate(world, rand, firstBlockXCoord, firstBlockYCoord, firstBlockZCoord);
        }
        for(int chanceForChuk = 0; chanceForChuk < 1; chanceForChuk++) {
        	Schematic spring = SchematicLoader.get("spring.schematic");
        	
        	int firstBlockXCoord = chunkX + rand.nextInt(16);
        	int firstBlockYCoord = rand.nextInt(200);
        	int firstBlockZCoord = chunkZ + rand.nextInt(16);
        	
        	 int i = 0;
             for(int cy = 0; cy < spring.height; cy++)
             for(int cz = 0; cz < spring.length; cz++)
             for(int cx = 0; cx < spring.width; cx++){

                     Block b = Block.getBlockById(spring.blocks[i]);
                     if(b!= Blocks.air)
                     {
                         world.setBlockToAir(cx + firstBlockXCoord , cy + firstBlockYCoord, cz + firstBlockZCoord);
                         world.setBlock(cx + firstBlockXCoord, cy + firstBlockYCoord, cz + firstBlockZCoord, b, spring.data[i] , 2);
                     }
                     i++;
             }
        }
}

private void generateNether(World world, Random rand, int chunkX, int chunkZ) {}
}

 

 

 

  Reveal hidden contents

 

 

My Line 52 is:              for(int cy = 0; cy < spring.height; cy++)

 

I don´t really know why, is the spring.height = 0 ?

Posted

I didn´t find it. My log (skip the errors with unable loading pngs, because it is something I forgot to add a texture.):

 

 

  Reveal hidden contents

 

Posted

I found a mistake, now there is an error : I can't load schematic because java.lang.NullPointerException

with the same Errorcode..

My Schematic.java:

package de.MhytRPG.www.structures;

import net.minecraft.nbt.NBTTagList;

public class Schematic{
    public  NBTTagList tileentities;
    public  short width;
    public  short height;
    public short length;
    public byte[] blocks;
    public byte[] data;
    public Schematic(NBTTagList tileentities, short width, short height, short length, byte[] blocks, byte[] data){
        this.tileentities = tileentities;
        this.width = width;
        this.height = height;
        this.length = length;
        this.blocks = blocks;
        this.data = data;
    }

}

 

and my SchematicLoader.java :

package de.MhytRPG.www.structures;

import java.io.File;
import java.io.InputStream;

import de.MhytRPG.www.MhytRPG;
import de.MhytRPG.www.structures.Schematic;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;

public class SchematicLoader {

public static Schematic get(String schemname){
        try {
            InputStream is = Schematic.class.getClass().getClassLoader().getResourceAsStream("assets" + File.separator + MhytRPG.MODID + File.separator + "schematics" + File.separator + schemname +".schematic");
            NBTTagCompound nbtdata = CompressedStreamTools.readCompressed(is);
            short width = nbtdata.getShort("Width");
            short height = nbtdata.getShort("Height");
            short length = nbtdata.getShort("Length");

            byte[] blocks = nbtdata.getByteArray("Blocks");
            byte[] data = nbtdata.getByteArray("Data");


            System.out.println("schem size:" + width + " x " + height + " x " + length);
            NBTTagList tileentities = nbtdata.getTagList("TileEntities", 10);
            is.close();

            return new Schematic(tileentities, width, height, length, blocks, data);
        } catch (Exception e) {
            System.out.println("I can't load schematic, because " + e.toString());
            return null;
        }
    }
}

 

I splitted them and write it to public static Schematic...  and changed the this. to Schematic. because the method need to performed with the Schematic.class

 

So what I have done wrong ?

 

EDIT : My location of schematic files: forge 1.7.10\src\main\resources\assets\mhytrpg\schematics

Posted

Maybe schematic is corrupt? If InputStream can't find file it throws FileNotFound exception. But in your case it's NullPointerException => CompressedStreamTools can't read stream correctly.

Posted

I tested it, if it throws a FileNotFoundException before I post this. I tried to import this schematic in WorldEdit and there is no error. So something other is going wrong. Do you know other programs with export something in the world to schematic ? Maybe WorldEdit mad something other in schematic so only WorldEdit can place them into the world ?

Posted

Replace

 

InputStream is = Schematic.class.getClass().getClassLoader().getResourceAsStream("assets" + File.separator + MhytRPG.MODID + File.separator + "schematics" + File.separator + schemname +".schematic");

 

With

 

String temp = "assets" + File.separator + MhytRPG.MODID + File.separator + "schematics" + File.separator + schemname +".schematic";
System.out.println("Trying to load " + temp);
InputStream is = Schematic.class.getClass().getClassLoader().getResourceAsStream(temp);

 

And look at log before crash.

Posted

Trying to load assets\mhytrpg\schematics\spring.schematic

and same error

(After first error i changed MODID to MODID.toLowercase() but the error was the same)

I think now he didn´t found the schematic but didn´t throw a FileNotFound exception ( i tested it)

 

EDIT: Here has to be the mistake after i added some more Sytem.Out.Println´s:

 

  Reveal hidden contents

 

 

 

Posted

I don't know what's wrong  :(

 

In my case it's works.

 

 

  Reveal hidden contents

 

Posted

I found the error:

  I forgot to declare SchematicLoader:

private Schematicloader sl = new SchematicLoader();

Now I get no error but my world doesn´t load fast (takes more than 1 minutes with only one structure)

 

How can I set my spawnrate lower or make Worldgenerating faster ?

My Class:

 

  Reveal hidden contents

 

 

Link to screenshot from world: http://prntscr.com/419ew9

Posted

I found a way:

int chance = new Random().nextInt(100);
if(int == 1) {
do this
}

 

But how I can generate a spring half in the underground and half in the Overworld?

Posted

I solved this problems. But now I have some questions about my method to create a structure in the worl:

 

My complet WorldGen.class :

 

  Reveal hidden contents

 

 

This happens after I made a world :

 

  Reveal hidden contents

 

 

1. What is the problem with my chest system ? Also I want to know how I can add more loot items in a chest, because there is only one item in each chest. And there have to be more different items! But I don´t know what I had done wrong..

 

2. And if a tower generate, the top is complet randomlly set ! But I want that only spinnwebs are generated randomly..

 

Thanks for your help!

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.