Talk:Development resources/Example Minecraft Classic Level Editing Class

Add topic
From Minecraft Wiki

Who authored this page, so credit can go where due?

Meh.. I don't care about credit, that's why I posted the original article anonymously. What I do care about is great new software being developed that makes Minecraft more fun.

LevelEditor.java[edit source]

getCoords(int index) is trying to use width and height but they don't exist in that method. I don't know the file structure well enough to tell what's going on here, should that be level.height and level.width? Can someone fix this? Jonfitt 16:28, 16 March 2011 (UTC)

Blocks.java[edit source]

This file is out of date, any chance someone could update it with the current block types?

Actually i have worked it out myself, BUT i cant remember how to do a code block in media wiki!

   public class Blocks 
   {
   	public static final byte air 				= (byte)0;
   	public static final byte rock 				= (byte)1;
   	public static final byte grass 				= (byte)2;
   	public static final byte dirt 				= (byte)3;
   	public static final byte stone 				= (byte)4;
   	public static final byte wood 				= (byte)5;
   	public static final byte shrub 				= (byte)6;
   	public static final byte blackrock 			= (byte)7;
   	public static final byte water 				= (byte)8;
   	public static final byte waterstill 			= (byte)9;
   	public static final byte lava 				= (byte)10;
   	public static final byte lavastill 			= (byte)11;
   	public static final byte sand 				= (byte)12;
   	public static final byte gravel 			= (byte)13;
   	public static final byte goldrock 			= (byte)14;
   	public static final byte iron 				= (byte)15;
   	public static final byte coal 				= (byte)16;
   	public static final byte trunk 				= (byte)17;
   	public static final byte leaf 				= (byte)18;
   	public static final byte sponge 			= (byte)19;
   	public static final byte glass 				= (byte)20;
   	public static final byte red 				= (byte)21;
   	public static final byte orange 			= (byte)22;
   	public static final byte yellow 			= (byte)23;
   	public static final byte lightgreen 			= (byte)24;
   	public static final byte green 				= (byte)25;
   	public static final byte aquagreen 			= (byte)26;
   	public static final byte cyan 				= (byte)27;
   	public static final byte lightblue 			= (byte)28;
   	public static final byte blue 				= (byte)29;
   	public static final byte purple 			= (byte)30;
   	public static final byte lightpurple 			= (byte)31;
   	public static final byte pink 				= (byte)32;
   	public static final byte darkpink 			= (byte)33;
   	public static final byte darkgrey 			= (byte)34;
   	public static final byte lightgrey 			= (byte)35;
   	public static final byte white 				= (byte)36;
   	public static final byte yellowflower 			= (byte)37;
   	public static final byte redflower 			= (byte)38;
   	public static final byte mushroom 			= (byte)39;
   	public static final byte redflowerdotted 		= (byte)40;
   	public static final byte goldsolid 			= (byte)41;
   }

58.104.6.192 04:37, 1 July 2009 (UTC)


Like this?--Quatroking - Row! Row! Fight the power! 06:32, 1 July 2009 (UTC)

Information[edit source]

Info on how this works would be helpfull.

This information is mostly for people who have knowledge of programming and programming Java in particular since the code is in Java. You use this information by reading and understanding the code, then apply or copy and past the code to your own programming project.

Point?[edit source]

Not sure what the point of this page is, since it's most likely outdated. Please explain.

Updated Blocks class (1 April 2012) and planetoids creator[edit source]

No this isn't an April fools joke, actually I love this simple API into the classic miencraft. I've done some updates to the Blocks class, fixed a few minor bugs in the LevelEditor class (and removed some helper methods, say, for building walls since they're really easy built yourself), then a new SpheresInTheSky class that draws a random sphere with specified surface and interior within the volume given. Coordinates are X forward/backward, Z left/right, and Y up/down, and are always used as ordered (x,y,z) triples.

Finally, the CreateWorld class then contains the main() runnable that is made to make some planetoids from glass, iron (hollow), and my favorite, solid gold with torches around them.

file Blocks.java[edit source]

/*
 * Convenience class for block constants
 * 
 * Last updated: 1 April 2012
 * 
 * Used on classic minecraft_server.jar,
 * map then imported using MCEdit version stable 33 and saved as alpha.
 * Map then opened in Minecraft single player version 1.2.4 with
 * the block behavior shown below.
 * 
 * Note: Minecraft world rules apply, otherwise blocks will not
 * show or pop off (mushrooms can't be in too much sun, flowers
 * need to be on soil, torches need to be attached to something, 
 * and so on).
 *
 * 
 */
package mc.level.pkg1203;

public class Blocks {
    
    public static final byte air                     = (byte)0;
    public static final byte stone                   = (byte)1;
    public static final byte grass                   = (byte)2;
    public static final byte dirt                    = (byte)3;
    public static final byte cobblestone             = (byte)4;
    public static final byte wooddenplanks           = (byte)5;
    public static final byte sapling                 = (byte)6;
    public static final byte bedrock                 = (byte)7;
    public static final byte water                   = (byte)8;
    public static final byte waterstill              = (byte)9;
    public static final byte lava                    = (byte)10;
    public static final byte lavastill               = (byte)11;
    public static final byte sand                    = (byte)12;
    public static final byte gravel                  = (byte)13;
    public static final byte goldore                 = (byte)14;
    public static final byte ironore                 = (byte)15;
    public static final byte coalore                 = (byte)16;
    public static final byte wood                    = (byte)17;
    public static final byte leaves                  = (byte)18;
    public static final byte sponge                  = (byte)19;
    public static final byte glass                   = (byte)20;
    
    // wool:
    public static final byte redwool                 = (byte)21;
    public static final byte orangewool              = (byte)22;
    public static final byte yellowwool              = (byte)23;
    public static final byte lightgreenwool          = (byte)24;
    public static final byte greenwool               = (byte)25;
    public static final byte cyanwool                = (byte)26;
    public static final byte lightbluewool           = (byte)27;
    public static final byte bluewool                = (byte)28;
    //                       purplewool              = (byte)29;
    public static final byte purplewool              = (byte)30;
    //                       darkpinkwool            = (byte)31;
    public static final byte darkpinkwool            = (byte)32;
    public static final byte pinkwool                = (byte)33;
    public static final byte darkgreywool            = (byte)34;
    public static final byte lightgreywool           = (byte)35;
    public static final byte whitewool               = (byte)36;
  
    public static final byte yellowflower            = (byte)37;
    public static final byte redflower               = (byte)38;
    public static final byte mushroom                = (byte)39;
    public static final byte redmushroom             = (byte)40;
    public static final byte gold                    = (byte)41;
    public static final byte iron                    = (byte)42;
    public static final byte slabsdouble             = (byte)43;
    public static final byte slab                    = (byte)44;
    public static final byte bricks                  = (byte)45;
    public static final byte tnt                     = (byte)46;
    public static final byte bookshelf               = (byte)47;
    public static final byte mossstone               = (byte)48;
    public static final byte obsidian                = (byte)49;
    public static final byte torch                   = (byte)50;
    public static final byte fire                    = (byte)51; // dysfunct?
    public static final byte waterflowing            = (byte)52;
    //                       obsidian                        53
    public static final byte chest                   = (byte)54; // facing X-direction
    //                       white wool                      55;
    public static final byte diamondore              = (byte)56;
    public static final byte diamond                 = (byte)57;
    public static final byte craftingtable           = (byte)58;
    public static final byte seeds                   = (byte)59;
    public static final byte farmland                = (byte)60;
    public static final byte furnace                 = (byte)61; // no visible opening
    public static final byte furnaceburning          = (byte)61; // defunct?
    public static final byte signpost                = (byte)63; // facing X-direction, empty
    public static final byte door                    = (byte)64; // defunct?
    public static final byte ladder                  = (byte)65; // defunct?
    public static final byte rails                   = (byte)66; // facing Z-direction
    public static final byte stonesteps              = (byte)67; // upward X-direction
    public static final byte signonwall              = (byte)68; // facing Z-direction, empty
    public static final byte lever                   = (byte)69; // only works facing Z-direction on wall
    public static final byte pressurepadstone        = (byte)70;
    public static final byte irondoor                = (byte)71; // defunct?
    public static final byte pressurepadwood         = (byte)72;
    public static final byte redstoneore             = (byte)73;
    public static final byte redstoneoreglowing      = (byte)74;
    public static final byte redstonetorchoff        = (byte)75;
    public static final byte redstonetorchon         = (byte)76;
    public static final byte button                  = (byte)77;
    public static final byte snowsurface             = (byte)78;
    public static final byte ice                     = (byte)79;
    public static final byte snow                    = (byte)80;
    public static final byte cactus                  = (byte)81;
    public static final byte clay                    = (byte)82;
    public static final byte sugarcane               = (byte)83;
    public static final byte jukebox                 = (byte)84;
    public static final byte fence                   = (byte)85;
    public static final byte pumpkin                 = (byte)86;
    public static final byte netherrack               = (byte)87;
    public static final byte soulsand                = (byte)88;
    public static final byte glowstone               = (byte)89;
    public static final byte netherportal            = (byte)90;
    public static final byte jackolantern            = (byte)91;
    public static final byte cake                    = (byte)92;
    public static final byte repeateroff             = (byte)93; // facing X-direction, 100ms
    public static final byte repeateron              = (byte)94; // facing X-direction, 100ms
    //                       repeater                        95     floating item
    public static final byte trapdoor                = (byte)96;
    public static final byte silverfishhidden        = (byte)97;
    public static final byte stonebricks             = (byte)98;
    public static final byte giantmushroombrown      = (byte)99; // interior only
    public static final byte giantmushroomred        = (byte)100; // interior only
    public static final byte ironbars                = (byte)101;
    public static final byte glasspane               = (byte)102;
    public static final byte melon                   = (byte)103;
    public static final byte pumpkingstem            = (byte)104;
    public static final byte melonstem               = (byte)105;
    public static final byte vines                   = (byte)106; // defunct?
    public static final byte fencegate               = (byte)107;
    public static final byte brickstairs             = (byte)108; // upward X-direction
    public static final byte stonebrickstairs        = (byte)109;
    public static final byte mycelium                = (byte)110;
    public static final byte lilypad                 = (byte)111;
    public static final byte netherbrick             = (byte)112;
    public static final byte netherbrickfence        = (byte)113;
    public static final byte netherbrickstairs       = (byte)114; // upward X-direction
    public static final byte netherwart              = (byte)115; // floating items
    public static final byte enchantmenttable        = (byte)116;
    public static final byte brewingstand            = (byte)117;
    public static final byte cauldron                = (byte)118;
    public static final byte endportal               = (byte)119;
    public static final byte endportalframe          = (byte)120;
    public static final byte endstone                = (byte)121;
    public static final byte dragonegg               = (byte)122;
    public static final byte redstonelampoff         = (byte)123;
    public static final byte redstonelampon          = (byte)124;

}

file LevelEditor.java[edit source]

package mc.level.pkg1203;

import java.io.*;
import java.text.DateFormat;
import java.util.Random;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class LevelEditor {
    
    private com.mojang.minecraft.level.Level level = null;
    private long randomSeed;
    private Random rnd;
    private int lX = 128; // left/right
    private int lY = 128; // bottom/top
    private int lZ = 128; // forward/backward
    private boolean lCreative = true;

    LevelEditor() {
        
        // create a new random generator
        
        randomSeed = 10000;
        rnd = new Random(randomSeed);
        
    }

    public Random getRnd() {
        return rnd;
    }
    
    public void setSeed(int newSeed) {
        // sets a new random seed
        
        randomSeed = newSeed;
        rnd = new Random(randomSeed);
        
    }
    
    public long getSeed() {
        return randomSeed;
    }
    
    public void setSize(int newX, int newY, int newZ) {
        
        lX = newX;
        lY = newY;
        lZ = newZ;
        
    }

    public int getSizeX() {
        return lX;
    }

    public int getSizeY() {
        return lY;
    }

    public int getSizeZ() {
        return lZ;
    }

    public com.mojang.minecraft.level.Level getLevel() {
        return level;
    }
    
    public void setLevel(com.mojang.minecraft.level.Level inLevel) {
        level = inLevel;
    }
    
    // load from file called filename
    public void load(String filename) {
        
        FileInputStream fis;
        GZIPInputStream gzis;
        ObjectInputStream in;
        DataInputStream inputstream;
        
        try {
            
            fis = new FileInputStream(filename);
            gzis = new GZIPInputStream(fis);
            inputstream = new DataInputStream(gzis);
            
            if((inputstream.readInt()) != 0x271bb788) {
                return;
            }
            
            if((inputstream.readByte()) > 2) {
                System.out.println("Error: Level version > 2, this is unexpected!");
                return;
            }
            
            in = new ObjectInputStream(gzis);
            level = (com.mojang.minecraft.level.Level) in.readObject();
            inputstream.close();
            in.close();
            System.out.println("Loading level "+filename+" successful");
            
        } catch( IOException | ClassNotFoundException ex) {
            
            ex.printStackTrace();
            
        }
        
        level.initTransient();
        
    }

    // save in file called filename
    public void save(String filename) {
        
        FileOutputStream fos;
        GZIPOutputStream gzos;
        ObjectOutputStream out;
        DataOutputStream outputstream;
        
        try {
            
            fos = new FileOutputStream(filename);
            gzos = new GZIPOutputStream(fos);
            outputstream = new DataOutputStream(gzos);
            outputstream.writeInt(0x271bb788);
            outputstream.writeByte(2);
            out = new ObjectOutputStream(gzos);
            out.writeObject(level);
            outputstream.close();
            out.close();
            
            System.out.println("Saving level " + filename + " successful");
            
        } catch(IOException ex) {
            
            ex.printStackTrace();
            
        }
        
    }

    // prints all there is to know about a level, except for the blocks data
    public void printInfo() {
        
        if (level == null) {
            return;
        }
        
        System.out.println("Level info:");
        System.out.println("name: " + level.name);
        System.out.println("creator: " + level.creator);
        System.out.println("createTime: "
                + (DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(level.createTime)));
        System.out.println("width: " + level.width);
        System.out.println("height: " + level.height);
        System.out.println("depth: " + level.depth);
        System.out.println("spawnpoint: [" + level.xSpawn + ", " + level.ySpawn + ", " + level.zSpawn + "]");
        System.out.println("spawn rotation: " + level.rotSpawn);
        
    }

    // safe to use method, return value let's you know if anything was changed
    public boolean setTile(int x, int y, int z, int t) {
        
        if (
            x >=0 && x < level.width &&
            y >=0 && y < level.depth &&
            z >=0 && z < level.height
        ) {
            if (t == 8 || t == 10) {
                level.setTile(x, y, z, t);
            } else {
                level.setTileNoUpdate(x, y, z, t);
            }
            return true;
        }
       
        return false;
        
    }

    public void clearBlocks() {
        for (int i = 0; i < level.blocks.length; i++) {
            level.blocks[i] = 0;
        }
    }

    public void setLevelSize(int x, int y, int z) {
        level.setData(x, y, z, new byte[x * y * z]);
    }

    public void testRnd() {
        // prints a few random number for fingerprinting the random seed
        
        System.out.println("Random seed: " + randomSeed);
        System.out.println("nextInt(1000): " + rnd.nextInt(1000));
        System.out.println("nextInt(1000): " + rnd.nextInt(1000));
        System.out.println("nextInt(1000): " + rnd.nextInt(1000));
        
    }
    
    public void drawLayer(int y, int t) {
        // create a layer of t on the plane (0, 0) through (lX, lZ)
        
        int x;
        int z;
        boolean success;
        
        System.out.println("drawLayer(" + y + ", " + t + ")");
        
        for (x = 0; x < this.lX; x++) {
            
            for (z = 0; z < this.lZ; z++) {
                
                success = this.setTile(x, y, z, t);
                
                if (success == false) {
                    System.out.println(
                            "setTile("
                            + x + ", " + y + ", " + z + ", " + t
                            + ") failed");
                }
                
            }
            
        }
        
    }
    
    public void drawSphere(int x, int y, int z, int radius, int t, int tFill) {
        // draw a sphere at (x,y,z) with radius and surface material t,
        // filled with material tFill (or don't modify interios if tFill < 0)
        
        // running sphere coordinate counters
        int xS;
        int yS;
        int zS;
        
        // distance to center
        double dist;
        
        // counters
        int cntBlocksSurface = 0;
        int cntBlocksInterior = 0;
        
        System.out.print(
                "drawSphere("
                + x + ", " + y + ", " + z + ", "
                + radius + ", "
                + t + ", "
                + tFill + ")");
        
        for (xS = -radius; xS < (radius + 1); xS++) {
            for (yS = -radius; yS < (radius + 1); yS++) {
                for (zS = -radius; zS < (radius + 1); zS++) {
                    
                    dist = (double) ((xS * xS) + (yS * yS) + (zS * zS));
                    dist = Math.sqrt(dist);
                    
                    if ( (dist - 0.5) < ((double) radius) ) {
                        // block is within sphere radius; check
                        // whether it is on the hull
                        
                        if ( (dist + 0.5) > ((double) radius) ) {
                            // this is a point on the surface
                            
                            this.setTile(x + xS, y + yS, z + zS, t);
                            cntBlocksSurface++;
                            
                        } else {
                            // inside
                            
                            if (tFill >= 0) {
                                // fill it (otherwise unchanged)
                                // (note: the setTile method checks for
                                // boundary violations and ignores silently)
                                
                                this.setTile(x + xS, y + yS, z + zS, tFill);
                                cntBlocksInterior++;
                                
                            }
                        
                        }
                        
                    }
                    
                } // zS loop end
            } // yS loop end
        } // zS loop end
        
        System.out.println(
                " - surface blocks: " + cntBlocksSurface 
                + " - interior: " + cntBlocksInterior);
        
    }
    
}

file SpheresInTheSky.java[edit source]

/*
 * SpheresInTheSky.java is a class that generates some random spheres
 * in a given volume. Spheres have a surface material and may be filled
 * with a different material (including air) or leave their interior
 * unchanged.
 * 
 */

package mc.level.pkg1203;

public class SpheresInTheSky {
    // creates a bunch of spheres in the specified volume
    
    public int minX;
    public int maxX;
    public int minY;
    public int maxY;
    public int minZ;
    public int maxZ;
    
    public int numSpheres = 30;
    public int minRadius = 5;
    public int maxRadius = 30;
    
    public int material = Blocks.glass;
    public int fill = Blocks.lava;
    
    private LevelEditor le;
    
    SpheresInTheSky(LevelEditor le) {
        // a level editor is required in the constructor
        
        this.le = le;
        
    }
    
    public void run() {
        // does the calculation
        
        int sphereNum;
        
        int thisRadius;
        int thisX;
        int thisY;
        int thisZ;
        
        for (sphereNum = 0; sphereNum < numSpheres; sphereNum ++) {
            // draw a few spheres

            thisRadius =
                    le.getRnd().nextInt(1 + maxRadius - minRadius)
                    + minRadius;
            thisX =
                    le.getRnd().nextInt(maxX - (minX + 2 * thisRadius))
                    + minX
                    + thisRadius;

            thisY =
                    le.getRnd().nextInt(maxY - (minY + 2 * thisRadius))
                    + minY
                    + thisRadius;

            thisZ =
                    le.getRnd().nextInt(maxZ - (minZ + 2 * thisRadius))
                    + minZ
                    + thisRadius;

            le.drawSphere(
                    thisX,
                    thisY,
                    thisZ,
                    thisRadius,
                    material,
                    fill);
            
        }
        
    }
    
}

file CreateWorld.java[edit source]

/*
 * The CreateWorld.java class holds the static voic main()
 * that creates a certain world.
 * 
 */

package mc.level.pkg1203;

public class CreateWorld {

    private String filename;
    
    public static void main(String [] args) {
        
        LevelEditor le = new LevelEditor();
        CreateWorld cw = new CreateWorld();
 
        // size of your world
        le.setSize(128, 128, 128);
        
        cw.filename =
                "server_level_"
                + le.getSizeX() + "_" + le.getSizeZ() + "_" + le.getSizeY()
                + ".dat";
        
        if(args.length > 0) {
            
            cw.filename = args[0];
            le.load(cw.filename);
            if (le.getLevel() == null) {
                System.out.println("Loading level " + cw.filename + " failed");
                return;
            }
            
        } else {
            
            le.setLevel(new com.mojang.minecraft.level.Level());
            
        }
        
        // test the random number generator and print fingerprint
        
        le.testRnd();
        
        // Do it!
        
        cw.createNewWorld(le);
        
        // Done. Save and print.
        
        le.save(cw.filename);
        le.printInfo();
       
        // Exit.
        
    }
    
    public void createNewWorld(LevelEditor le) {
        // this methods does the actual setting of blocks
        
        le.setLevelSize(le.getSizeX(), le.getSizeY(), le.getSizeZ());
        le.clearBlocks();

        // draw some water
        
        le.drawLayer(1, Blocks.waterstill);
        le.drawLayer(2, Blocks.waterstill);
        le.drawLayer(3, Blocks.waterstill);
        
        // draw a few spheres
       
        SpheresInTheSky spheres = new SpheresInTheSky(le);
        
        spheres.minX = 2;
        spheres.maxX = 125;
        spheres.minY = 8;
        spheres.maxY = 127;
        spheres.minZ = 2;
        spheres.maxZ = 125;
        spheres.minRadius = 3;
        spheres.maxRadius = 10;

        // draw ten glass spheres filled with air
        
        spheres.material = Blocks.glass;
        spheres.fill = Blocks.air;
        spheres.numSpheres = 10;
        
        spheres.run();

        // draw five hollow iron spheres
        
        spheres.material = Blocks.iron;
        spheres.numSpheres = 5;
        spheres.run();

        // draw five solid gold sphere with torches around
        
        spheres.material = Blocks.torch;
        spheres.fill = Blocks.gold;
        spheres.run();
        
        // draw one lava sphere in glass
        
        spheres.material = Blocks.glass;
        spheres.fill = Blocks.lava;
        spheres.numSpheres = 1;
        
        spheres.run();
                
        // last step: draw some bedrock to make sure nobody falls
        // out of this world ...
        
        le.drawLayer(0, Blocks.bedrock);

        // all is created; let the level find a spawn
        
        le.getLevel().findSpawn();
        le.getLevel().creator = "yourname";
        le.getLevel().name = "lvl-seed" + le.getSeed();
        le.getLevel().createTime = System.currentTimeMillis();
        le.getLevel().creativeMode = true;
        
    }
        
}