-
Posts
153 -
Joined
-
Last visited
Everything posted by WorldsEnder
-
Opening GUI on player's client from server
WorldsEnder replied to twixthehero's topic in Modder Support
Do you have a GUIHandler yet? If not then write one and register it with NetworkRegistry.instance().registerGuiHandler(this, new your_GUIHandler()); in the @Mod file. This tells Forge to call your GUIHandler if the first argument in player.openGUI(mod, id, world, arg1, arg2, arg3) (I'll refer to those variables), if now the var mod is your mod then Forge sends a call to the registered GUIHandler. The your_GUIHandler implements IGuiHanlder and would feature two mthods: public Object getServerGuiElement(int, EntityPlayer, World, int, int, int) and public Object getClientGuiElement(int, EntityPlayer, World, int, int, int). If you call openGUI with the argument I mentioned then your GUIHandler would get those variables passed as following: One call (from the server) goes to registered_GUIHandler.getServerGuiElement(id, player, world, arg1, arg2, arg3) the other call (from the client) goes to registered_GUIHandler.getClientGuiElement(id, player, world, arg1, arg2, arg3). Now all you have to do is switching the id. If the id is equal to the id of your GUI_TEAM_SELECT (choose any id you want as long as you keep it the same in all files, preferably an public static (final) int GUI_TEAM_SELECT_ID; in one class.) you then return null for the server (as you normally return the container, the opened GUI features), and for the client you return a new instance of your GUI. Easy as that. CARE: when using buttons I can't help you much by now as I don't know how to write a PackageHandler (which you have to do) -
If you want just additional data to your player I would suppose to write an IPlayerTracker or add something if you have one yet. This is a convenient method to get the method onPlayerLogin(EntityPlayer player) called every time a player logs in. Then you get the NBTString (getEntityData()) and read from there. You store your read values in some sort of static Helper-Class (e.g. class HelperHelper implements IPlayerTracker{ public static final instance = new HelperHelper(); private static HashMap<EntityPlayer, a_class_that_can_store_your_values> playerData = new HashMap<EntityPlayer, a_class_that_can_store_your_values>(); public static a_class_that_can_store_your_values getValuesFor(EntityPlayer player) { return playerData.get(player); } @Override public void onPlayerLogin(EntityPlayer player) { if(player.getEntityData().hasKey("what_so_ever") { playerData.put(player, readFromNBTStream(player.getEntityData().getCompoundTag("what_so_ever"); }else{ playerData.put(player, new a_class_that_can_store_your_values()); } @Override public void onPlayerLogout(EntityPlayer player) { NBTTagCompound toWriteTo = new NBTTagCompound(); playerData.get(player).writeToNBTTagCompound(toWriteTo); player.getEntityData().setCompoundTag("what_so_ever", toWriteTo); } private a_class_that_can_store_your_values readFromNBTStream(NBTTagCompound playerCompound) { a_class_that_can_store_your_values toReturn = new a_class_that_can_store_your_values(); toReturn.readFromNBTTagCompound(playerCompound); return toReturn; } ... include additional methods from IPlayerTracker } Please note that this is only what I would suppose, maybe you have to edit it slightly. Please note: your a_class_that_can_store_your_values has to feature the two public methods readFromNBTTagCompound(NBTTagCompound someName) and writeToNBTTagCompound(NBTTagCompound someOtherName). I hope you know how to read and write from/to NBTTagCompounds correctly. Maybe you also want to edit the method onPlayerLogin slightly cause it will always give you the default values of the NBTTagCompounds. You can check if the player has data already by calling player.getEntityData().hasKey("what_so_ever") and deciding what default values you put in. Please note.3: you have to register your IPlayerTracker in your @Mod file preferably by typing GameRegistry.registerPlayerTracker(HelperHelper.instance); Please note.4: also, all text with "_" has to be replaced with any name you choose as far as it is the same you use for the same placeholder. Please note.5: if I have any typos please be kind and don't mention them if they are not really, really, really, really, really stuhpid
-
Uff dude, you don't want to begin with something easier D: To be able to "sit" in a chair you would have to modify the boundingBoxes of the Player so that Minecraftmechanics won't push them out again. The other thing to do is just placing the mob at the right position and angles and then using the PlayerAPI (no link though, google it) to modify the arms and legs. I guess I can't give you much detail here because I'm in kinda hurry. Maybe later. Hope this helps a bit, sincerely Me
-
Opening a GUI on right-clicking a mob that is player-persistant
WorldsEnder replied to WorldsEnder's topic in Modder Support
You don't need all that fancy stuff, I found out. I was just a bit stumbled by all the code I found http://www.minecraftforge.net/wiki/Containers_and_GUIs. Then I realized that you use the Container on both, CLIENT and SERVER and I was released from the code-ghosts that haunted me All works fine. As it is MY mob I just use the method interact and it now works fine. Only thing that does not work yet is placing items inot the GUI. They just get thrown out when I click on the slot but I am very much convinced that I can get it working myself. Thanks for the help -
Hi guys, like the title says I want to open a GUI when you rightclick my mob. I know the methods and so but Player#openGUI does only feature the arguments @Mod, World, int, int, int (I suppose the ints are coordinates) so I don't know what to do here. Second problem is that I want the Inventory in the GUI to be persistant over all worlds and blocks just like the enderchest. Here is what I have so far: package de.gmx.worldsbegin.entity; import de.gmx.worldsbegin.MobsterHunterMinedomUnite; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.scoreboard.ScorePlayerTeam; import net.minecraft.util.ChunkCoordinates; import net.minecraft.world.World; public class EntityMHVillager extends EntityLiving{ private String name; public EntityMHVillager(World par1World) { super(par1World); } @Override protected boolean isAIEnabled() { return true; } @Override public boolean interact(EntityPlayer player) { // I know that I have to do something here... but what? return true; } @Override public int getMaxHealth() { return 10; } } Not much huh?
-
Works all fine, I tested it and I found no glitches/bugs or anything If YOU find and don't fear to post them, I'll see what I did wrong. Also a non-centered BB would be easy with 3 new vars (I am sure you know how to if youu know a bit of prgramming).
-
I've overridden setPosition: /EDIT wrong solution: it doesn't really work at all... Now I have weird glitches were the entity is not where it belongs to and I can't really explain why EDIT: fixed it, works fine now EDIT2: I did not tell the truth... it does not work all the time... will inspect that EDIT3: finally... I found a solution to keep the boundingBox centered on your entity (at least x and z -axis). No more wishes I guess: @Override public void setPosition(double par1, double par2, double par3) { AxisAlignedBB b = this.boundingBox; double boxSX = b.maxX - b.minX; double boxSY = b.maxY - b.minY; double boxSZ = b.maxZ - b.minZ; this.boundingBox.setBounds(posX - boxSX/2D, posY, posZ - boxSZ/2D, posX + boxSX/2D, posY + boxSY, posZ + boxSZ/2D); }
-
So I did this: public EntityFelyne(World par1World) { super(par1World); this.boundingBox.setBounds(0D, 0D, 0D, 0D, 0D, 0D); } @Override public AxisAlignedBB getCollisionBox(Entity par1Entity) { return boundingBox; } @Override public AxisAlignedBB getBoundingBox() { return boundingBox; } Still, when I enter debug mode.... box[-33.80000001192093, 66.0, 140.19999998807907 -> -33.19999998807907, 67.79999995231628, 140.80000001192093]; and this is totally the zone I can hit the entity in. Anything you wanna say about this?
-
Okay, I've found critical point of code that leads us to no control over this thing...: EntityRenderer: line 304ff. float f2 = entity.getCollisionBorderSize(); -> AxisAlignedBB axisalignedbb = entity.boundingBox.expand((double)f2, (double)f2, (double)f2); MovingObjectPosition movingobjectposition = axisalignedbb.calculateIntercept(vec3, vec32); if (axisalignedbb.isVecInside(vec3)) { if (0.0D < d2 || d2 == 0.0D) { this.pointedEntity = entity; d2 = 0.0D; } } else if (movingobjectposition != null) { double d3 = vec3.distanceTo(movingobjectposition.hitVec); if (d3 < d2 || d2 == 0.0D) { this.pointedEntity = entity; d2 = d3; } } This leads us to the problem. As a modder I don't know how to influence the entity.boundingBox as it is declared final in Entity... I am not used to make a request so if one of you is more experienced in requesting something from the dev-team, pls do it. All they have to do is to swap this special line of code from entity.boundingBox to entity.getBoundingBox() or entity.getCollisionBox(). Either of them would do fine.
-
Right at the start: this.boundingBox is final I didn't know the getCollisionBox() method so I will try it After trying it out I'm gonna report the result in this thread.
-
So I just override getBoundingBox() ? cause I tried that out and it did nothing... : @Override public AxisAlignedBB getBoundingBox() { return AxisAlignedBB.getBoundingBox(0, 0, 0, 0, 0, 0); }
-
I want to add a custom hitbox for my mob. Not this BoundingBox to define when the mob is been pushed but the hitbox which defines when the mob is being damaged. I think nobody needs more to know? In advance Me
-
Hm, ok I see that point... O think I'll just do that. Though an answer would come in handy, you never know where you my need it.
-
I want the mob to die on its own after he "counted" to 250 and I don't trust laggy minecraft... It's some sort of boss you have to kill fast because I don't set the life to 0 but I call this.setDead() (<- evil me). Btw the mob is registered with an updateFrequency of 3 for those of you who want to know
-
All the default mobs in minecraft use 3 I belive... And I would really recommend you to us that value too. It seems like perfectly fitting and is kinda always enough.
-
Hi guys, I have an entity. This entity should update on ticks ofc. Now the problem is that I want to use realtime, which means that I use System.currentTimeMillis(). I update my variable lastRecieved etc. It all works fine and stuff. The problem is that I don't want the counter to count up while the game is paused. So I thought: "I just let the entity receive some sort of notification (preferably through an Event) and turn the counter off on GamePause and back on, with a new time ofc, when the pause is over. But how can I do the trick? It seems like there is no event raised when the game is paused... neither when it is un-paused. Some tips from community? Thanks in advance Me
-
Okay I figured it out by myself (this forum isn't very helpful at all :'( ) But: for anyone after me reading this: entityInit() is not initCreature() entityInit(): everytime a new creature is created. This means that this is called BEFORE reading from the NBT. initCreature(): called AFTER NBT-read at spawn. I think the entity is fully initialized at this point which means that you can get the worldObj and tweek your entity in regard of the enviroment it spawned in.
-
Your item class just has to implement ISpecialArmor like this: .... public class YourArmor implements ISpecialArmor { ... your methods public void damageArmor(EntityLiving entity, ItemStack stack, DamageSource source, int damage, int slot){} ... anything else } and done. your armor should now not take damage anymore
-
I began to write some code but as I began to write a mob it was all okay and worked fine. The only thing is that the mob does not get written into the NBT of the save. (I checked with NBTExplorer) Here are my classes [spoiler=mainclass]package de.gmx.worldsbegin; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.BitSet; import javax.annotation.PreDestroy; import net.minecraft.client.model.ModelBat; import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.entity.RenderBlaze; import net.minecraft.client.renderer.entity.RenderLiving; import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.EnumCreatureType; import net.minecraft.tileentity.MobSpawnerBaseLogic; import net.minecraft.world.SpawnerAnimals; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.biome.SpawnListEntry; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.ForgeSubscribe; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.Block; import cpw.mods.fml.common.Mod.Init; import cpw.mods.fml.common.Mod.Item; import cpw.mods.fml.common.Mod.PostInit; import cpw.mods.fml.common.Mod.PreInit; 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; import cpw.mods.fml.common.registry.EntityRegistry; import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration; import cpw.mods.fml.common.registry.GameData; import cpw.mods.fml.common.registry.LanguageRegistry; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; import de.gmx.worldsbegin.entities.EntityTigrex; @Mod(modid="MonsterHunterMinedomUnite", name="Monster Hunter Minedom Unite", version="a0.1") @NetworkMod(clientSideRequired=true, serverSideRequired=false) @MCVersion(value="1.5.1") public class MonsterHunterMinedomUnite { private static BitSet freeEntityIds; private ArrayList<String> preloadedTexture; //Load config etc. @PreInit private void preInitMod(FMLPreInitializationEvent fpreie) { freeEntityIds = new BitSet(256); freeEntityIds.flip(0, 255); //TODO well... that's not all e.g. config etc. } //Setup the blocks etc. @Init private void initMod(FMLInitializationEvent fie) { this.registerBlocks(); this.registerAndNameItems(); this.registerCustomBiomes(); this.registerCustomMobs(); this.registerMHMUEvents(); //TODO maybe something else.. not sure yet } //Communicate with other mods etc. @PostInit private void postInit(FMLPostInitializationEvent fpostie) { //TODO maybe ... just mark } //Save config and everything else @PreDestroy private void saveAndQuit() { } private void registerBlocks() { //TODO maybe some blocks, like "mining station" and gathering plants etc. } private void registerAndNameItems() { //TODO all of them items... that are many //TODO them armory and weapons puha } private void registerCustomSmelting() { //TODO well I don't know... there is no such thing in Monster Hunter, is there? } private void registerCustomCrafting() { //TODO puh all them combinations them combinations... Str-C, Str-V } private void registerCustomBiomes() { //TODO Do you even quest? } private void registerCustomMobs() { //global EntityRegistry.registerGlobalEntityID(EntityTigrex.class, "Tigrex", EntityRegistry.findGlobalUniqueEntityId(), 0xffffff, 0x001100); //... //local EntityRegistry.registerModEntity(EntityTigrex.class, "Tigrex", this.findUniqueEntityIdAndRegister(),this, 84, 3, true); //... //name them all LanguageRegistry.instance().addStringLocalization("entity.Tigrex.name", "Tigrex"); } private void registerMHMUEvents() { } //Only call this when you really want to register an entity private static int findUniqueEntityIdAndRegister(){ int id = MonsterHunterMinedomUnite.freeEntityIds.nextSetBit(0); if(id==-1){ throw new RuntimeException("No ids left... Oh god I'm spamming lol"); } MonsterHunterMinedomUnite.freeEntityIds.set(id); return id; } } [spoiler=a superclass]package de.gmx.worldsbegin.entities; import java.util.HashMap; import de.gmx.worldsbegin.events.FlashBombEvent; import de.gmx.worldsbegin.events.SonicBombEvent; import net.minecraft.entity.EntityLiving; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeSubscribe; public abstract class EntityMinedom extends EntityLiving{ /** * the attack that is currently performed */ protected MonsterAttack currentattack; /** * the current frame in the animatic flow */ protected int currentAttackFrame = 0; /** * the rank of this monster */ protected Rank rank; //methods public EntityMinedom(World par1World, Rank rank) { super(par1World); } public abstract HashMap<MonsterAttack, Integer> getAttacksWithWeight(); public abstract byte getBrokenParts(); @Override public void initCreature() { super.initCreature(); //timeEnragedLeft this.dataWatcher.addObject(16, Integer.valueOf((int) 0)); //durationFlashedLeft this.dataWatcher.addObject(17, Integer.valueOf((int) 0)); //durationSonicLeft (by sonic grenade e.g.) this.dataWatcher.addObject(18, Integer.valueOf((int) 0)); } @Override public void writeEntityToNBT(NBTTagCompound par1nbtTagCompound) { super.writeEntityToNBT(par1nbtTagCompound); par1nbtTagCompound.setInteger("enragedTimeLeft", this.dataWatcher.getWatchableObjectInt(16)); par1nbtTagCompound.setInteger("flashedTimeLeft", this.dataWatcher.getWatchableObjectInt(17)); par1nbtTagCompound.setInteger("sonicTimeLeft", this.dataWatcher.getWatchableObjectInt(18)); par1nbtTagCompound.setInteger("rank", this.rank.ordinal()); } @Override public void readEntityFromNBT(NBTTagCompound par1nbtTagCompound) { super.readEntityFromNBT(par1nbtTagCompound); this.dataWatcher.updateObject(16, par1nbtTagCompound.getInteger("enragedTimeLeft")); this.dataWatcher.updateObject(17, par1nbtTagCompound.getInteger("flashedTimeLeft")); this.dataWatcher.updateObject(18, par1nbtTagCompound.getInteger("sonicTimeLeft")); this.rank = Rank.values()[par1nbtTagCompound.getInteger("rank")]; } /** * @return - Whether the entity is in a enraged state, mostly * used to give it more attack/def. */ public boolean isEnraged() { return this.dataWatcher.getWatchableObjectByte(16)>0; } /** * @return - the frame the animation is momentarily at */ public final int getCurrentAttackFrame() { return this.currentAttackFrame; } /** * @return - the attack that is currently executed */ public final MonsterAttack getCurrentAttack() { return this.currentattack; } /** * Called when a flash bomb explodes in the world. Check where it exploded and do your stuff. */ @ForgeSubscribe(receiveCanceled=false) protected void onFlashBomb(FlashBombEvent fbe) { } /** * Called when a sonic bomb explodes in the world. Check where it exploded and stuff. */ @ForgeSubscribe(receiveCanceled=false) protected void onSonicBomb(SonicBombEvent sbe) { } //enum public enum Rank { low, high, G; } } [spoiler=The Entity]package de.gmx.worldsbegin.entities; import java.util.HashMap; import net.minecraft.entity.ai.EntityAIFleeSun; import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.ai.EntityAISwimming; import net.minecraft.entity.ai.EntityAIWander; import net.minecraft.entity.monster.EntityMob; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.world.World; /** * * Specified data to watch: * dataWatcher(19): byte containing bitwise booleans: * b&1 - head broken * b&2 - rightWing broken * b&4 - leftWing broken * b&8 - tail broken * @author Carbon * */ public class EntityTigrex extends EntityMinedom{ /**Tigrex is a multiBBEntity thus we need an array*/ protected EntityTigrexPart[] entityParts; protected EntityTigrexPart head1; protected EntityTigrexPart head2; protected EntityTigrexPart body1; //TODO more bodyparts... the real ones... protected static MonsterAttack[] perfomableAttacks; public EntityTigrex(World p1) { this(p1, Rank.low); } public EntityTigrex(World p1, Rank rank) { super(p1, rank); this.tasks.addTask(0, new EntityAISwimming(this)); //TODO write an AI to add here //add texture } @Override public int getMaxHealth() { // TODO Auto-generated method stub return 4;//TODO a real health here not debug-value } @Override protected boolean isAIEnabled() { return true;//At least I think so... } /** * This only adjusts the body-parts and spawn particles. * Movement should be done by the AI. */ @Override public void onLivingUpdate() { super.onLivingUpdate(); //TODO something at least.... //TODO update the animation and particles } @Override public void writeEntityToNBT(NBTTagCompound par1nbtTagCompound) { super.writeEntityToNBT(par1nbtTagCompound); par1nbtTagCompound.setBoolean("headBroken", (this.dataWatcher.getWatchableObjectByte(19)&1)==1); par1nbtTagCompound.setBoolean("rightWingBroken", (this.dataWatcher.getWatchableObjectByte(19)>>1&1)==1); par1nbtTagCompound.setBoolean("leftWingBroken", (this.dataWatcher.getWatchableObjectByte(19)>>2&1)==1); par1nbtTagCompound.setBoolean("tailCut", (this.dataWatcher.getWatchableObjectByte(19)>>3&1)==1); } @Override public void readEntityFromNBT(NBTTagCompound par1nbtTagCompound) { super.readEntityFromNBT(par1nbtTagCompound); byte toDataWatcher = 0; if(par1nbtTagCompound.getBoolean("headBroken")) toDataWatcher += 1; if(par1nbtTagCompound.getBoolean("rightWingBroken")) toDataWatcher += (1<<1); if(par1nbtTagCompound.getBoolean("leftWingBroken")) toDataWatcher += (1<<2); if(par1nbtTagCompound.getBoolean("tailCut")) toDataWatcher += (1<<3); this.dataWatcher.updateObject(19, toDataWatcher); } @Override public void initCreature() { super.initCreature(); //broken Parts this.dataWatcher.addObject(19, Byte.valueOf((byte) 0)); //TODO ini the bodyParts } @Override public HashMap<MonsterAttack, Integer> getAttacksWithWeight() { HashMap<MonsterAttack, Integer> returnMap= new HashMap<MonsterAttack, Integer>(); for(int i=0;i<this.entityParts.length;i++){ returnMap.put(this.perfomableAttacks, 5);//TODO real values not just 5 for every attack.... } return returnMap; } /** * @return - compare this bitwise: * b&1 - whether head is broken * b&2 - leftWing is broken * b&4 - rightWing is broken * b&8 - tail is cutoff */ public byte getBrokenParts() { return this.dataWatcher.getWatchableObjectByte(17); } /** * Should return false as collision is handeled by the sub-bodyparts. */ @Override public boolean canBeCollidedWith() { return false; } /** * Damage should by applied though the sub-bodyparts so this returns false. * @return - always false */ @Override public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) { return true;//FIXME debug value set to false } /** * */ public boolean attackEntityFromPart(EntityTigrexPart par1partFrom, DamageSource par1DamageSource, int par2) { return !this.isDead; } } I think this should be enough.... if you need anything more to know why this isn't saved just tell me
-
I began to write some code but as I began to write a mob it was all okay and worked fine. The only thing is that the mob does not get written into the NBT of the save. (I checked with NBTExplorer) Here are my classes [spoiler=mainclass]package de.gmx.worldsbegin; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.BitSet; import javax.annotation.PreDestroy; import net.minecraft.client.model.ModelBat; import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.entity.RenderBlaze; import net.minecraft.client.renderer.entity.RenderLiving; import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.EnumCreatureType; import net.minecraft.tileentity.MobSpawnerBaseLogic; import net.minecraft.world.SpawnerAnimals; import net.minecraft.world.biome.BiomeGenBase; import net.minecraft.world.biome.SpawnListEntry; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.ForgeSubscribe; import cpw.mods.fml.client.registry.RenderingRegistry; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.Block; import cpw.mods.fml.common.Mod.Init; import cpw.mods.fml.common.Mod.Item; import cpw.mods.fml.common.Mod.PostInit; import cpw.mods.fml.common.Mod.PreInit; 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; import cpw.mods.fml.common.registry.EntityRegistry; import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration; import cpw.mods.fml.common.registry.GameData; import cpw.mods.fml.common.registry.LanguageRegistry; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; import de.gmx.worldsbegin.entities.EntityTigrex; @Mod(modid="MonsterHunterMinedomUnite", name="Monster Hunter Minedom Unite", version="a0.1") @NetworkMod(clientSideRequired=true, serverSideRequired=false) @MCVersion(value="1.5.1") public class MonsterHunterMinedomUnite { private static BitSet freeEntityIds; private ArrayList<String> preloadedTexture; //Load config etc. @PreInit private void preInitMod(FMLPreInitializationEvent fpreie) { freeEntityIds = new BitSet(256); freeEntityIds.flip(0, 255); //TODO well... that's not all e.g. config etc. } //Setup the blocks etc. @Init private void initMod(FMLInitializationEvent fie) { this.registerBlocks(); this.registerAndNameItems(); this.registerCustomBiomes(); this.registerCustomMobs(); this.registerMHMUEvents(); //TODO maybe something else.. not sure yet } //Communicate with other mods etc. @PostInit private void postInit(FMLPostInitializationEvent fpostie) { //TODO maybe ... just mark } //Save config and everything else @PreDestroy private void saveAndQuit() { } private void registerBlocks() { //TODO maybe some blocks, like "mining station" and gathering plants etc. } private void registerAndNameItems() { //TODO all of them items... that are many //TODO them armory and weapons puha } private void registerCustomSmelting() { //TODO well I don't know... there is no such thing in Monster Hunter, is there? } private void registerCustomCrafting() { //TODO puh all them combinations them combinations... Str-C, Str-V } private void registerCustomBiomes() { //TODO Do you even quest? } private void registerCustomMobs() { //global EntityRegistry.registerGlobalEntityID(EntityTigrex.class, "Tigrex", EntityRegistry.findGlobalUniqueEntityId(), 0xffffff, 0x001100); //... //local EntityRegistry.registerModEntity(EntityTigrex.class, "Tigrex", this.findUniqueEntityIdAndRegister(),this, 84, 3, true); //... //name them all LanguageRegistry.instance().addStringLocalization("entity.Tigrex.name", "Tigrex"); } private void registerMHMUEvents() { } //Only call this when you really want to register an entity private static int findUniqueEntityIdAndRegister(){ int id = MonsterHunterMinedomUnite.freeEntityIds.nextSetBit(0); if(id==-1){ throw new RuntimeException("No ids left... Oh god I'm spamming lol"); } MonsterHunterMinedomUnite.freeEntityIds.set(id); return id; } } [spoiler=a superclass]package de.gmx.worldsbegin.entities; import java.util.HashMap; import de.gmx.worldsbegin.events.FlashBombEvent; import de.gmx.worldsbegin.events.SonicBombEvent; import net.minecraft.entity.EntityLiving; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeSubscribe; public abstract class EntityMinedom extends EntityLiving{ /** * the attack that is currently performed */ protected MonsterAttack currentattack; /** * the current frame in the animatic flow */ protected int currentAttackFrame = 0; /** * the rank of this monster */ protected Rank rank; //methods public EntityMinedom(World par1World, Rank rank) { super(par1World); } public abstract HashMap<MonsterAttack, Integer> getAttacksWithWeight(); public abstract byte getBrokenParts(); @Override public void initCreature() { super.initCreature(); //timeEnragedLeft this.dataWatcher.addObject(16, Integer.valueOf((int) 0)); //durationFlashedLeft this.dataWatcher.addObject(17, Integer.valueOf((int) 0)); //durationSonicLeft (by sonic grenade e.g.) this.dataWatcher.addObject(18, Integer.valueOf((int) 0)); } @Override public void writeEntityToNBT(NBTTagCompound par1nbtTagCompound) { super.writeEntityToNBT(par1nbtTagCompound); par1nbtTagCompound.setInteger("enragedTimeLeft", this.dataWatcher.getWatchableObjectInt(16)); par1nbtTagCompound.setInteger("flashedTimeLeft", this.dataWatcher.getWatchableObjectInt(17)); par1nbtTagCompound.setInteger("sonicTimeLeft", this.dataWatcher.getWatchableObjectInt(18)); par1nbtTagCompound.setInteger("rank", this.rank.ordinal()); } @Override public void readEntityFromNBT(NBTTagCompound par1nbtTagCompound) { super.readEntityFromNBT(par1nbtTagCompound); this.dataWatcher.updateObject(16, par1nbtTagCompound.getInteger("enragedTimeLeft")); this.dataWatcher.updateObject(17, par1nbtTagCompound.getInteger("flashedTimeLeft")); this.dataWatcher.updateObject(18, par1nbtTagCompound.getInteger("sonicTimeLeft")); this.rank = Rank.values()[par1nbtTagCompound.getInteger("rank")]; } /** * @return - Whether the entity is in a enraged state, mostly * used to give it more attack/def. */ public boolean isEnraged() { return this.dataWatcher.getWatchableObjectByte(16)>0; } /** * @return - the frame the animation is momentarily at */ public final int getCurrentAttackFrame() { return this.currentAttackFrame; } /** * @return - the attack that is currently executed */ public final MonsterAttack getCurrentAttack() { return this.currentattack; } /** * Called when a flash bomb explodes in the world. Check where it exploded and do your stuff. */ @ForgeSubscribe(receiveCanceled=false) protected void onFlashBomb(FlashBombEvent fbe) { } /** * Called when a sonic bomb explodes in the world. Check where it exploded and stuff. */ @ForgeSubscribe(receiveCanceled=false) protected void onSonicBomb(SonicBombEvent sbe) { } //enum public enum Rank { low, high, G; } } [spoiler=The Entity]package de.gmx.worldsbegin.entities; import java.util.HashMap; import net.minecraft.entity.ai.EntityAIFleeSun; import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.ai.EntityAISwimming; import net.minecraft.entity.ai.EntityAIWander; import net.minecraft.entity.monster.EntityMob; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.world.World; /** * * Specified data to watch: * dataWatcher(19): byte containing bitwise booleans: * b&1 - head broken * b&2 - rightWing broken * b&4 - leftWing broken * b&8 - tail broken * @author Carbon * */ public class EntityTigrex extends EntityMinedom{ /**Tigrex is a multiBBEntity thus we need an array*/ protected EntityTigrexPart[] entityParts; protected EntityTigrexPart head1; protected EntityTigrexPart head2; protected EntityTigrexPart body1; //TODO more bodyparts... the real ones... protected static MonsterAttack[] perfomableAttacks; public EntityTigrex(World p1) { this(p1, Rank.low); } public EntityTigrex(World p1, Rank rank) { super(p1, rank); this.tasks.addTask(0, new EntityAISwimming(this)); //TODO write an AI to add here //add texture } @Override public int getMaxHealth() { // TODO Auto-generated method stub return 4;//TODO a real health here not debug-value } @Override protected boolean isAIEnabled() { return true;//At least I think so... } /** * This only adjusts the body-parts and spawn particles. * Movement should be done by the AI. */ @Override public void onLivingUpdate() { super.onLivingUpdate(); //TODO something at least.... //TODO update the animation and particles } @Override public void writeEntityToNBT(NBTTagCompound par1nbtTagCompound) { super.writeEntityToNBT(par1nbtTagCompound); par1nbtTagCompound.setBoolean("headBroken", (this.dataWatcher.getWatchableObjectByte(19)&1)==1); par1nbtTagCompound.setBoolean("rightWingBroken", (this.dataWatcher.getWatchableObjectByte(19)>>1&1)==1); par1nbtTagCompound.setBoolean("leftWingBroken", (this.dataWatcher.getWatchableObjectByte(19)>>2&1)==1); par1nbtTagCompound.setBoolean("tailCut", (this.dataWatcher.getWatchableObjectByte(19)>>3&1)==1); } @Override public void readEntityFromNBT(NBTTagCompound par1nbtTagCompound) { super.readEntityFromNBT(par1nbtTagCompound); byte toDataWatcher = 0; if(par1nbtTagCompound.getBoolean("headBroken")) toDataWatcher += 1; if(par1nbtTagCompound.getBoolean("rightWingBroken")) toDataWatcher += (1<<1); if(par1nbtTagCompound.getBoolean("leftWingBroken")) toDataWatcher += (1<<2); if(par1nbtTagCompound.getBoolean("tailCut")) toDataWatcher += (1<<3); this.dataWatcher.updateObject(19, toDataWatcher); } @Override public void initCreature() { super.initCreature(); //broken Parts this.dataWatcher.addObject(19, Byte.valueOf((byte) 0)); //TODO ini the bodyParts } @Override public HashMap<MonsterAttack, Integer> getAttacksWithWeight() { HashMap<MonsterAttack, Integer> returnMap= new HashMap<MonsterAttack, Integer>(); for(int i=0;i<this.entityParts.length;i++){ returnMap.put(this.perfomableAttacks, 5);//TODO real values not just 5 for every attack.... } return returnMap; } /** * @return - compare this bitwise: * b&1 - whether head is broken * b&2 - leftWing is broken * b&4 - rightWing is broken * b&8 - tail is cutoff */ public byte getBrokenParts() { return this.dataWatcher.getWatchableObjectByte(17); } /** * Should return false as collision is handeled by the sub-bodyparts. */ @Override public boolean canBeCollidedWith() { return false; } /** * Damage should by applied though the sub-bodyparts so this returns false. * @return - always false */ @Override public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) { return true;//FIXME debug value set to false } /** * */ public boolean attackEntityFromPart(EntityTigrexPart par1partFrom, DamageSource par1DamageSource, int par2) { return !this.isDead; } } I think this should be enough.... if you need anything more to know why this isn't saved just tell me