Jump to content

Constructive Criticism Requested


Danickar

Recommended Posts

So I just finished a simple mod that creates and plays a game of Tic Tac Toe in the world.  The board, made of 9 blocks containing their tile entities is created by using a ttt item.  This is my first attempt at something more complicated than a block or item and with code that requires multiple parts talking to each other.  I am sure there are better ways to do a lot of what I have done, so I am posting all of the code here for anyone to review and critique.

 

Main file:

 

package powell.games;

import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import powell.games.item.Items;
import powell.games.network.CommonProxy;
import powell.games.block.Blocks;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;

@Mod(modid=ModInfo.ID, name=ModInfo.NAME, version=ModInfo.VERSION)
@NetworkMod(channels = {"gamesChannel"}, clientSideRequired=true, serverSideRequired = true)


public class Games
{
// The instance of your mod that Forge uses.
@Instance(value = ModInfo.ID)
public static Games instance;

public static CreativeTabs tabGames = new CreativeTabs("tabGames") 
{
	public ItemStack getIconItemStack() 
	{
		return new ItemStack(Block.glowStone, 1, 0);
	}
};

public static final int DIMENSIONID = 7;

// Says where the client and server 'proxy' code is loaded.
@SidedProxy(clientSide="powell.games.network.ClientProxy", serverSide="powell.games.network.CommonProxy")
public static CommonProxy proxy;

@EventHandler // used in 1.6.2
//@PreInit    // used in 1.5.2
public void preInit(FMLPreInitializationEvent event) 
{
	Items.init();
	Blocks.init();
}


@EventHandler // used in 1.6.2
//@Init       // used in 1.5.2
public void load(FMLInitializationEvent event) 
{
	Items.load();
	Blocks.load();
	Blocks.registerTileEntities();
}

@EventHandler // used in 1.6.2
//@PostInit   // used in 1.5.2
public void postInit(FMLPostInitializationEvent event) 
{
	// Stub Method

}
}

 

 

Block files:

 

package powell.games.block;

import net.minecraft.block.Block;
import powell.games.entity.tileentity.TTTBlockEntity;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;

public class Blocks
{
public static Block tttBlock;

public static void init()
{
	tttBlock = new TTTBlock(1442);
}

public static void load()
{
	GameRegistry.registerBlock(tttBlock, "tttBlock");
	LanguageRegistry.addName(tttBlock, "Tic Tac Toe Block");
}

public static void registerTileEntities() 
{
	GameRegistry.registerTileEntity(TTTBlockEntity.class, "tttBlockEntity");
}
}

 

 

 

package powell.games.block;

import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Icon;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import powell.games.Games;
import powell.games.entity.tileentity.TTTBlockEntity;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class TTTBlock extends BlockContainer
{
private Icon full;
private Icon x;
private Icon o;
private boolean showX;
private boolean showO;

public TTTBlock(int par1)
{
	super(par1, Material.rock);
	setStepSound(Block.soundStoneFootstep);
	setCreativeTab(Games.tabGames);
	setHardness(500000F);
	setResistance(500000F);
	setUnlocalizedName("tttBlock");
	showX = showO = false;
}

@Override
public boolean isOpaqueCube()
{
	return false;
}

@SideOnly(Side.CLIENT)
public void registerIcons(IconRegister iconRegister)
{

	//block texture
	blockIcon = iconRegister.registerIcon("games:tictactoe");
	x = iconRegister.registerIcon("games:x");
	o = iconRegister.registerIcon("games:o");

}


@Override
public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
{
	if(!showX && !showO)
	{
		System.out.println("was right clicked");
		//showX = true;
		TTTBlockEntity be = (TTTBlockEntity)par1World.getBlockTileEntity(par2, par3, par4);
		be.makePlay(par1World);

	}


	return true;
}

@Override
public TileEntity createNewTileEntity(World world)
{
	return new TTTBlockEntity();
}

@Override
public Icon getIcon(int side, int meta) 
{
	//System.out.println("inside getIcon with meta " + meta);
	return meta == 0 ? blockIcon : meta == 1 ? x  : o;
}



}

 

 

Entity:

 

package powell.games.entity;


import powell.games.Games;
import cpw.mods.fml.common.registry.EntityRegistry;

public class Entities
{
private static int modEntityID = 0;

public static void init()
{
	EntityRegistry.registerModEntity(TTTEntity.class, "Tic Tac Toe Game", ++modEntityID, Games.instance, 64, 10, true);
}
}

 

 

 

package powell.games.entity;

import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import powell.games.block.Blocks;
import powell.games.entity.tileentity.*;

public class TTTEntity extends Entity
{
private int turn;


public TTTEntity(World par1World)
{
	super(par1World);
	turn = 0;
}

public TTTEntity(World world, int x, int y, int z)
{
	super(world);
	turn = 0;

	for(int xx = 0; xx < 3; xx++)
	{
		for(int zz = 0; zz < 3; zz++)
		{
			System.out.println("X " + (x+xx) + " Y " + y + " Z " + (z+zz));
			world.setBlock(x, y, z + zz, Blocks.tttBlock.blockID);
			TTTBlockEntity bleh = (TTTBlockEntity)world.getBlockTileEntity(x, y, z +zz);
			bleh.registerBoard(this);
		}
		y++;
	}
}

@Override
protected void entityInit()
{
	// TODO Auto-generated method stub

}

@Override
protected void readEntityFromNBT(NBTTagCompound nbttagcompound)
{
	// TODO Auto-generated method stub

}

@Override
protected void writeEntityToNBT(NBTTagCompound nbttagcompound)
{
	// TODO Auto-generated method stub

}

public boolean getPlay()
{
	return (turn++ % 2) == 0;
}

}

 

 

Tile Entity:

 

package powell.games.entity.tileentity;

import powell.games.entity.TTTEntity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;

public class TTTBlockEntity extends TileEntity
{
private boolean turn;
private boolean played;
private TTTEntity board;

public TTTBlockEntity()
{
	turn = true;
	played = false;
}

public void makePlay(World world)
{
	if(!played)
	{
		System.out.println("in the make play");
		turn = board.getPlay();
		world.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, turn ? 1 : 2, 3);
		played = !played;
	}


}

@Override
public void writeToNBT(NBTTagCompound compound) 
{
	super.writeToNBT(compound);

}

@Override
public void readFromNBT(NBTTagCompound compound) 
{
	super.readFromNBT(compound);

}

public void registerBoard(TTTEntity b)
{
	board = b;
}
}

 

 

Item:

 

package powell.games.item;

import net.minecraft.item.Item;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;

public class Items
{
public static Item ttt;

public static void init()
{
	ttt = new TTTItem(9500);
}

public static void load()
{
	GameRegistry.registerItem(ttt,"tttItem");
	LanguageRegistry.addName(ttt, "Tic Tac Toe");

}
}

 

 

 

package powell.games.item;

import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import powell.games.Games;
import powell.games.entity.TTTEntity;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class TTTItem extends Item
{
public TTTItem(int par1)
{
	super(par1);
	this.maxStackSize = 1;
	this.setCreativeTab(Games.tabGames);
	this.setUnlocalizedName("tttItem");
}

@SideOnly(Side.CLIENT)
@Override
public void registerIcons(IconRegister iconRegister)//updateIcons
{
	this.itemIcon = iconRegister.registerIcon("games:tictactoe");
}


public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
    {
        int i1 = par3World.getBlockId(par4, par5, par6);
        
        System.out.println("Block id is " + i1);
        par3World.spawnEntityInWorld(new TTTEntity(par3World, par4, par5 + 1, par6));
        
        return true;


    }
}

 

Link to comment
Share on other sites

I don't understand why you used an Item and an Entity.

You can place the blocks themselves, and they already contain the TileEntity.

 

My advice:

Merge the entity-placing-blocks code into the "item use" method, then move that content into the "block placed" method, finally delete everything about the item and the entity. The TileEntity should store everything related to the play.

Not optimal, but better.

Then you could improve the thing by using only one TileEntity, for example in the middle block.

With two block states based on metadata, only one having the TileEntity. (do not use BlockContainer, prefer hasTileEntity(metadata)...)

The "block placed" method would check around for other similar blocks, and set the middle block to the state with a TileEntity, when the board is complete.

The "block activated" method would check around for a block with the tileentity, and write to it.

Link to comment
Share on other sites

My thought behind the Entity itself was a central place to keep track of the game.  For TTT, a rather simple game for sure, it is keeping track of whose turn it is, so that clicking on any of the blocks creates the appropriate X or O.  I wasn't sure of the best way to get a blocks to find a TileEntity to figure out whose turn it was.

Link to comment
Share on other sites

You could do something like this in your TileEntity:

private boolean mark = true;
private String[] players = new String[2];

public boolean getNextMark(){//returns a boolean opposite each time, equivalent to 0 or X
    mark = !mark;
    return mark;
}

public boolean isNextPlayer(EntityPlayer player){//check that a player can play this game, on this turn
    return player.username.equals(players[mark?0:1]);
}

public boolean setPlayer(EntityPlayer player){//sets a player, return true if it was added to the game
    if(players[0]==null){
        players[0] = player.username;
        return true;
    }else if(players[1]==null){
        players[1] = player.username;
        return true;
    }
    return false;
}

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • SLOT DANA : Situs Slot Gacor Nagaliga Deposit Via DANA 10.000
    • NAGALIGA :  Agen Taruhan Mix Parlay Bola EURO Terpercaya Di Indonesia Nagaliga merupakan situs taruhan  judi bola euro dan slot gacor terbaik menyediakan link alternatif terbaik dan pastinya bisa di akses di seluruh penjuru dunia. Ayo meriahkan EURO bersama situs Nagaliga kemenangan berapapun pasti dibayar lunas tanpa ada kendala.
    • I have no idea how a UI mod crashed a whole world but HUGE props to you man, just saved me +2 months of progress!  
    • So i know for a fact this has been asked before but Render stuff troubles me a little and i didnt find any answer for recent version. I have a custom nausea effect. Currently i add both my nausea effect and the vanilla one for the effect. But the problem is that when I open the inventory, both are listed, while I'd only want mine to show up (both in the inv and on the GUI)   I've arrived to the GameRender (on joined/net/minecraft/client) and also found shaders on client-extra/assets/minecraft/shaders/post and client-extra/assets/minecraft/shaders/program but I'm lost. I understand that its like a regular screen, where I'd render stuff "over" the game depending on data on the server, but If someone could point to the right client and server classes that i can read to see how i can manage this or any tip would be apreciated
    • Let me try and help you with love spells, traditional healing, native healing, fortune telling, witchcraft, psychic readings, black magic, voodoo, herbalist healing, or any other service your may desire within the realm of african native healing, the spirits and the ancestors. I am a sangoma and healer. I could help you to connect with the ancestors , interpret dreams, diagnose illness through divination with bones, and help you heal both physical and spiritual illness. We facilitate the deepening of your relationship to the spirit world and the ancestors. Working in partnership with one\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\’s ancestors is a gift representing a close link with the spirit realm as a mediator between the worlds.*   Witchdoctors, or sorcerers, are often purveyors of mutis and charms that cause harm to people. we believe that we are here for only one purpose, to heal through love and compassion.*   African people share a common understanding of the importance of ancestors in daily life. When they have lost touch with their ancestors, illness may result or bad luck. Then a traditional healer, or sangoma, is sought out who may prescribe herbs, changes in lifestyle, a career change, or changes in relationships. The client may also be told to perform a ceremony or purification ritual to appease the ancestors.*   Let us solve your problems using powerful African traditional methods. We believe that our ancestors and spirits give us enlightenment, wisdom, divine guidance, enabling us to overcome obstacles holding your life back. Our knowledge has been passed down through centuries, being refined along the way from generation to generation. We believe in the occult, the paranormal, the spirit world, the mystic world.*   The services here are based on the African Tradition Value system/religion,where we believe the ancestors and spirits play a very important role in society. The ancestors and spirits give guidance and counsel in society. They could enable us to see into the future and give solutions to the problems affecting us. We use rituals, divination, spells, chants and prayers to enable us tackle the task before us.*   I have experience in helping and guiding many people from all over the world. My psychic abilities may help you answer and resolve many unanswered questions
  • Topics

×
×
  • Create New...

Important Information

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