Jump to content

JimiIT92

Members
  • Posts

    866
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by JimiIT92

  1. I guess you can just call the same code but with different position. For instance, let's say you have 2 parts of the structure, and the second is 20 block away on the X axis from the first part. I think you can generate the first part passing a position as a parameter and then re-call that function but passing position.add(20, 0, 0) and of course the name of the other structure part
  2. Ok, just figured out how to get the exact size of the strucutre (and it was easier than i thought). Just use template.getSize(). Note that despite the fact it return a block pos this will have the size of the structure. So, if you do template.getSize().getX() you'll have how "long" the structure is (how many blocks on the X axis the structure have). If you do template.getSize().getZ() you'll get how "deep" the structure is (how many blocks on the Z axis the structure have). If you do template.getSize().getY() you'll get how "tall" the structure is (how many blocks on the Y axis the structure have). Knowing this is then easy to check if a structure can spawn. For example i use this for loop that (in case the structure can spawn) will place it at the center of the choosen area for (int i = -1 * template.getSize().getX()/2; i < template.getSize().getX()/2 + 1; i++) { for (int j = -1 * template.getSize().getZ(); j < template.getSize().getZ()/2 + 1; j++) { if (!world.getBlockState(pos.add(i, 0, j)).getBlock().equals(Blocks.GRASS) && !world.getBlockState(pos.add(i, 0, j)).getBlock().equals(Blocks.DIRT)) { flag = false; break; } } }
  3. Ahahahaah just remember that the getTopOrSolidBlock works for the first block of the structure (so you can have a structure that is one block on ground and the rest in the air). I'm trying to find how to get the structure dimension to check if there's enough space to generate, i'll update as soon as i find it
  4. That will be much easier. So i can, for instance, have two rolls for a golden apple but in one i set an entryName:"regular" and in the other i set an entryName:"enchanted"? If so then is really good and will avoid using the LootTableLoadEvent
  5. That's ruin a bit the loot table system. I think the easiset way to make it work is to handle the LootTableLoadEvent, in there if i load this loot table than i add the enchanted golden apple to the loot PS: Can you provide me a link where is explained how to write a loot table from scratch? In this case i've copied a vanilla one but i want to understand how it exactly works (in particular pools and rolls). Thanks for your help
  6. Yes, as i said this is the copy of the desert pyramid loot table file, wich rolls for both regular and enchanted golden apples. Beside of this, if i want to roll for different values o a item/block, how can i do (since they'll have the same name)? For example, i want that in the chest can be Stone and Granite, both have the "minecraft:stone" id so what should i write in the loot table?
  7. Ok, so now i have a different error. The json file looks like this { "pools": [ { "name": "pagoda", "rolls": { "min": 2, "max": 4 }, "entries": [ { "type": "item", "name": "minecraft:diamond", "functions": [ { "function": "set_count", "count": { "min": 1, "max": 3 } } ], "weight": 5 }, { "type": "item", "name": "minecraft:iron_ingot", "functions": [ { "function": "set_count", "count": { "min": 1, "max": 5 } } ], "weight": 15 }, { "type": "item", "name": "minecraft:gold_ingot", "functions": [ { "function": "set_count", "count": { "min": 2, "max": 7 } } ], "weight": 15 }, { "type": "item", "name": "minecraft:emerald", "functions": [ { "function": "set_count", "count": { "min": 1, "max": 3 } } ], "weight": 15 }, { "type": "item", "name": "minecraft:bone", "functions": [ { "function": "set_count", "count": { "min": 4, "max": 6 } } ], "weight": 25 }, { "type": "item", "name": "minecraft:spider_eye", "functions": [ { "function": "set_count", "count": { "min": 1, "max": 3 } } ], "weight": 25 }, { "type": "item", "name": "minecraft:rotten_flesh", "functions": [ { "function": "set_count", "count": { "min": 3, "max": 7 } } ], "weight": 25 }, { "type": "item", "name": "minecraft:saddle", "weight": 20 }, { "type": "item", "name": "minecraft:iron_horse_armor", "weight": 15 }, { "type": "item", "name": "minecraft:golden_horse_armor", "weight": 10 }, { "type": "item", "name": "minecraft:diamond_horse_armor", "weight": 5 }, { "type": "item", "name": "minecraft:book", "weight": 20, "functions": [ { "function": "enchant_randomly" } ] }, { "type": "item", "name": "minecraft:golden_apple", "weight": 20 }, { "type": "item", "name": "minecraft:golden_apple", "weight": 2, "functions": [ { "function": "set_data", "data": 1 } ] }, { "type": "empty", "weight": 15 } ] }, { "rolls": 4, "entries": [ { "type": "item", "name": "minecraft:bone", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] }, { "type": "item", "name": "minecraft:gunpowder", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] }, { "type": "item", "name": "minecraft:rotten_flesh", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] }, { "type": "item", "name": "minecraft:string", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] }, { "type": "item", "name": "minecraft:sand", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] } ] } ] } And the error is this Loot Table "mw:pagoda_chest" Duplicate entry name "minecraft:golden_apple" for pool #-1 entry #13 I think is related to the fact the the pool rolls for both regular golden apple and enchanted one, and i think that removing one of this will solve the problem, but if i want to keep it both how can i do?
  8. I have a structure in my world and i want to add a custom loot table to it's chests. I've tried doing this TileEntityChest chest = (TileEntityChest)world.getTileEntity(key); chest.setLootTable(new ResourceLocation(MW.MODID, "pagoda_chest"), new Random().nextLong()); Where "pagoda_chest" is the json loot table file, located in the loot_tables folder in assets, but as far as i load the structure this error pops out Couldn't load loot table mw:pagoda_chest from file:/C:/Users/Jimi/Documents/Minecraft%20Modding/MineWorld/bin/assets/mw/loot_tables/pagoda_chest.json com.google.gson.JsonParseException: Loot Table "mw:pagoda_chest" Missing `name` entry for pool #0 at net.minecraftforge.common.ForgeHooks.readPoolName(ForgeHooks.java:1114) ~[ForgeHooks.class:?] at net.minecraft.world.storage.loot.LootPool$Serializer.deserialize(LootPool.java:152) ~[LootPool$Serializer.class:?] at net.minecraft.world.storage.loot.LootPool$Serializer.deserialize(LootPool.java:147) ~[LootPool$Serializer.class:?] at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58) ~[TreeTypeAdapter.class:?] at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) ~[TypeAdapterRuntimeTypeWrapper.class:?] at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:72) ~[ArrayTypeAdapter.class:?] at com.google.gson.Gson.fromJson(Gson.java:803) ~[Gson.class:?] at com.google.gson.Gson.fromJson(Gson.java:868) ~[Gson.class:?] at com.google.gson.Gson$1.deserialize(Gson.java:126) ~[Gson$1.class:?] at net.minecraft.util.JsonUtils.deserializeClass(JsonUtils.java:378) ~[JsonUtils.class:?] at net.minecraft.util.JsonUtils.deserializeClass(JsonUtils.java:400) ~[JsonUtils.class:?] at net.minecraft.world.storage.loot.LootTable$Serializer.deserialize(LootTable.java:209) ~[LootTable$Serializer.class:?] at net.minecraft.world.storage.loot.LootTable$Serializer.deserialize(LootTable.java:204) ~[LootTable$Serializer.class:?] at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58) ~[TreeTypeAdapter.class:?] at com.google.gson.Gson.fromJson(Gson.java:803) ~[Gson.class:?] at com.google.gson.Gson.fromJson(Gson.java:768) ~[Gson.class:?] at com.google.gson.Gson.fromJson(Gson.java:717) ~[Gson.class:?] at com.google.gson.Gson.fromJson(Gson.java:689) ~[Gson.class:?] at net.minecraftforge.common.ForgeHooks.loadLootTable(ForgeHooks.java:1038) ~[ForgeHooks.class:?] at net.minecraft.world.storage.loot.LootTableManager$Loader.loadBuiltinLootTable(LootTableManager.java:148) [LootTableManager$Loader.class:?] at net.minecraft.world.storage.loot.LootTableManager$Loader.load(LootTableManager.java:71) [LootTableManager$Loader.class:?] at net.minecraft.world.storage.loot.LootTableManager$Loader.load(LootTableManager.java:52) [LootTableManager$Loader.class:?] at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3524) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2317) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2280) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2195) [guava-17.0.jar:?] at com.google.common.cache.LocalCache.get(LocalCache.java:3934) [guava-17.0.jar:?] at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3938) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4821) [guava-17.0.jar:?] at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4827) [guava-17.0.jar:?] at net.minecraft.world.storage.loot.LootTableManager.getLootTableFromLocation(LootTableManager.java:39) [LootTableManager.class:?] at net.minecraft.tileentity.TileEntityLockableLoot.fillWithLoot(TileEntityLockableLoot.java:55) [TileEntityLockableLoot.class:?] at net.minecraft.tileentity.TileEntityChest.createContainer(TileEntityChest.java:495) [TileEntityChest.class:?] at net.minecraft.entity.player.EntityPlayerMP.displayGUIChest(EntityPlayerMP.java:861) [EntityPlayerMP.class:?] at net.minecraft.block.BlockChest.onBlockActivated(BlockChest.java:420) [blockChest.class:?] at net.minecraft.server.management.PlayerInteractionManager.processRightClickBlock(PlayerInteractionManager.java:477) [PlayerInteractionManager.class:?] at net.minecraft.network.NetHandlerPlayServer.processRightClickBlock(NetHandlerPlayServer.java:706) [NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock.processPacket(CPacketPlayerTryUseItemOnBlock.java:68) [CPacketPlayerTryUseItemOnBlock.class:?] at net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock.processPacket(CPacketPlayerTryUseItemOnBlock.java:13) [CPacketPlayerTryUseItemOnBlock.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15) [PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) [?:1.8.0_101] at java.util.concurrent.FutureTask.run(Unknown Source) [?:1.8.0_101] at net.minecraft.util.Util.runTask(Util.java:25) [util.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:742) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:687) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:536) [MinecraftServer.class:?] at java.lang.Thread.run(Unknown Source) [?:1.8.0_101] Note that the file i use for the loot table is the exact copy of the desert pyramid chest loot table file. This is the json file { "pools": [ { "rolls": { "min": 2, "max": 4 }, "entries": [ { "type": "item", "name": "minecraft:diamond", "functions": [ { "function": "set_count", "count": { "min": 1, "max": 3 } } ], "weight": 5 }, { "type": "item", "name": "minecraft:iron_ingot", "functions": [ { "function": "set_count", "count": { "min": 1, "max": 5 } } ], "weight": 15 }, { "type": "item", "name": "minecraft:gold_ingot", "functions": [ { "function": "set_count", "count": { "min": 2, "max": 7 } } ], "weight": 15 }, { "type": "item", "name": "minecraft:emerald", "functions": [ { "function": "set_count", "count": { "min": 1, "max": 3 } } ], "weight": 15 }, { "type": "item", "name": "minecraft:bone", "functions": [ { "function": "set_count", "count": { "min": 4, "max": 6 } } ], "weight": 25 }, { "type": "item", "name": "minecraft:spider_eye", "functions": [ { "function": "set_count", "count": { "min": 1, "max": 3 } } ], "weight": 25 }, { "type": "item", "name": "minecraft:rotten_flesh", "functions": [ { "function": "set_count", "count": { "min": 3, "max": 7 } } ], "weight": 25 }, { "type": "item", "name": "minecraft:saddle", "weight": 20 }, { "type": "item", "name": "minecraft:iron_horse_armor", "weight": 15 }, { "type": "item", "name": "minecraft:golden_horse_armor", "weight": 10 }, { "type": "item", "name": "minecraft:diamond_horse_armor", "weight": 5 }, { "type": "item", "name": "minecraft:book", "weight": 20, "functions": [ { "function": "enchant_randomly" } ] }, { "type": "item", "name": "minecraft:golden_apple", "weight": 20 }, { "type": "item", "name": "minecraft:golden_apple", "weight": 2, "functions": [ { "function": "set_data", "data": 1 } ] }, { "type": "empty", "weight": 15 } ] }, { "rolls": 4, "entries": [ { "type": "item", "name": "minecraft:bone", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] }, { "type": "item", "name": "minecraft:gunpowder", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] }, { "type": "item", "name": "minecraft:rotten_flesh", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] }, { "type": "item", "name": "minecraft:string", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] }, { "type": "item", "name": "minecraft:sand", "weight": 10, "functions": [ { "function": "set_count", "count": { "min": 1, "max": 8 } } ] } ] } ] } So how can i load this custom loot table?
  9. @SureenInk I simply pass this block pos as position to spawn the structure worldIn.getTopSolidOrLiquidBlock(pos) Consider that i use this in the decoration function of my biome, but i guess that you can use it in the world generator too @trollworkout The nbt file is generated using Structure Block in the game it-self. Note that the structure can't be larger than 32x32x32. Once i saved the strucutre i then put into a folder (in my mod assets) called "structures", so i can load it in every world i want
  10. EDIT: I've looked at the Strucutre Block class and i found out how to load a structure. But for some reason if i generate a new world and (for example) try to load this structure right-clicking an item it seems like the game can't find the structure (wich is stored in the structures folder into resources). This is the dummy item class i use to "spawn" the structure public class ItemMW extends Item { public ItemMW(CreativeTabs tab) { this.setCreativeTab(tab); } @Override public ActionResult<ItemStack> onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand) { if (!worldIn.isRemote) this.func_189714_c(playerIn.getPosition(), worldIn); return super.onItemRightClick(itemStackIn, worldIn, playerIn, hand); } public boolean func_189714_c(BlockPos pos, World world) { WorldServer worldserver = (WorldServer) world; MinecraftServer minecraftserver = world.getMinecraftServer(); TemplateManager templatemanager = worldserver.getStructureTemplateManager(); Template template = templatemanager.func_189942_b(minecraftserver, new ResourceLocation(MW.MODID + ":" + "structures/pagoda.nbt")); if(template == null) { System.out.println("NO STRUCTURE"); return false; } BlockPos blockpos2 = template.getSize(); IBlockState iblockstate = world.getBlockState(pos); world.notifyBlockUpdate(pos, iblockstate, iblockstate, 3); PlacementSettings placementsettings = (new PlacementSettings()).setMirror(Mirror.NONE) .setRotation(Rotation.NONE).setIgnoreEntities(false).setChunk((ChunkPos) null) .setReplacedBlock((Block) null).setIgnoreStructureBlock(false); template.addBlocksToWorldChunk(world, pos.add(0, 1, 0), placementsettings); return true; } } The NBT file is stored into resources-assets-mw-structures-pagoda.nbt (mw is the mod id) EDIT 2: Found out a way to make it works. The problem was (as i suspected) in the ResourceLocation, that for some reason pointed at a wrong location. By changing that i can spawn my structure and also integrating this function into (for example) a biome class i can spawn it randomly in the world using the nbt file public void loadStructure(BlockPos pos, World world, String name) { WorldServer worldserver = (WorldServer) world; MinecraftServer minecraftserver = world.getMinecraftServer(); TemplateManager templatemanager = worldserver.getStructureTemplateManager(); ResourceLocation loc = new ResourceLocation(MW.MODID, name); Template template = templatemanager.func_189942_b(minecraftserver, loc); if (template != null) { IBlockState iblockstate = world.getBlockState(pos); world.notifyBlockUpdate(pos, iblockstate, iblockstate, 3); PlacementSettings placementsettings = (new PlacementSettings()).setMirror(Mirror.NONE) .setRotation(Rotation.NONE).setIgnoreEntities(false).setChunk((ChunkPos) null) .setReplacedBlock((Block) null).setIgnoreStructureBlock(false); template.addBlocksToWorldChunk(world, pos.add(0, 1, 0), placementsettings); } }
  11. I'm wondering if there is a way to spawn a structure using the Structure Block exported file. For instance, i want to spawn this structure in my world But instead of defining a class that tells block by block wich block to set in the world i want that the world generator actually "loads" the nbt files containing the structure (generated using the structure block) For instance this file https://mega.nz/#!1M9EEDhA!MGMd4w9ii67jutDBh_s5w1ZdT7uYpVPhJtGEe1JqfNk Is this possibile or i still have to defining that big file? If it is how can i make it?
  12. Ok, i will check it out and hopefully managed to work
  13. I never used reflection so i could make some mistakes. However i now have this, no errors are given but is this correct or again something is wrong? if(event.getWorld().provider instanceof WorldProviderSurface) { ChunkProviderOverworld chunkGenerator = (ChunkProviderOverworld) ((WorldServer)event.getWorld()).getChunkProvider().chunkGenerator; Field mapGen = ReflectionHelper.findField(ChunkProviderOverworld.class, "scatteredFeatureGenerator"); mapGen.setAccessible(true); MapGenScatteredFeature map = (MapGenScatteredFeature)mapGen.get(ChunkProviderOverworld.class); Method getStructure = MapGenScatteredFeature.class.getDeclaredMethod("getStructureAt", MapGenScatteredFeature.class); getStructure.setAccessible(true); StructureStart structurestart = (StructureStart) getStructure.invoke(event.getPos()); if (structurestart != null && structurestart instanceof MapGenScatteredFeature.Start && !structurestart.getComponents().isEmpty()) { StructureComponent structurecomponent = (StructureComponent)structurestart.getComponents().get(0); if(structurecomponent instanceof ComponentScatteredFeaturePieces.DesertPyramid) { event.getList().add(new SpawnListEntry(EntityZombie.class, 20, 1, 3)); } } }
  14. Ok, so i got this right now @SubscribeEvent public void onTerrainGen(WorldEvent.PotentialSpawns event) { if(event.getWorld().provider instanceof WorldProviderSurface) { ChunkProviderOverworld chunkGenerator = (ChunkProviderOverworld) ((WorldServer)event.getWorld()).getChunkProvider().chunkGenerator; MapGenScatteredFeature map; Field[] fields = ChunkProviderOverworld.class.getFields(); for (Field element : fields) try { if (element.get(ChunkProviderOverworld.class) != null) { if (element.getName().equals("scatteredFeatureGenerator")) { map = (MapGenScatteredFeature)element.get(ChunkProviderOverworld.class); break; } } } catch (IllegalArgumentException e) { System.err.println("Illegal argument passed as Block to register"); e.printStackTrace(); } catch (IllegalAccessException e) { System.err.println("Illegal access while registering a Block"); e.printStackTrace(); } StructureStart structurestart = map.getStructureAt(event.getPos()); if (structurestart != null && structurestart instanceof MapGenScatteredFeature.Start && !structurestart.getComponents().isEmpty()) { StructureComponent structurecomponent = (StructureComponent)structurestart.getComponents().get(0); if(structurecomponent instanceof ComponentScatteredFeaturePieces.DesertPyramid) { event.getList().add(new SpawnListEntry(EntityZombie.class, 20, 1, 3)); } } } } But when i do this StructureStart structurestart = map.getStructureAt(event.getPos()); it gives me an error telling me that getStructureAt is not visible. How can i solve this?
  15. Thank you for the answer but i did not understand how to get the Chunk Provider since if i do event.getWorld().getChunkProvider() then i can't access to chunkGenerator field
  16. For instance, i want that Husks can spawn inside the Desert Pyramid like Wither Skeletons does in the Nether Fortress. But i've tried using the InitMapGenEvent but in the EventType there's nothing that can lead to the pyramid (while instead there is the NETHER_BRIDGE type that lead to Wither Skeleton spawn). So how can i force the game to spawn an entity in a specific structure (in this case a Husk in a Pyramid)?
  17. So i've tried doing this, checking if the world is not remote if (Minecraft.getMinecraft().objectMouseOver != null && Minecraft.getMinecraft().objectMouseOver.entityHit != null) { if (Minecraft.getMinecraft().objectMouseOver.entityHit instanceof EntityLiving && !player.worldObj.isRemote) { Entity target = Minecraft.getMinecraft().objectMouseOver.entityHit; if (target instanceof EntityPlayer) target.attackEntityFrom(DamageSource.generic, 1.0F + (10.0F - ((EntityPlayer) target).getHealth())); else target.attackEntityFrom(DamageSource.generic, 10.0F); } } But it still doesn't deal damage
  18. What i'm trying to do is to deal damage to an entity or a player i'm looking at. If is a player the damage is based on his health. I already got working the "get the entity a player is looking at" part, so if i look, for instance a cow, the code knows that the player is looking a cow. What is not working is the damage part. At the moment i have this if (Minecraft.getMinecraft().objectMouseOver != null && Minecraft.getMinecraft().objectMouseOver.entityHit != null) { if (Minecraft.getMinecraft().objectMouseOver.entityHit instanceof EntityLiving) { Entity target = Minecraft.getMinecraft().objectMouseOver.entityHit; if (target instanceof EntityPlayer) target.attackEntityFrom(DamageSource.generic, 1.0F + (10.0F - ((EntityPlayer) target).getHealth())); else target.attackEntityFrom(DamageSource.generic, 10.0F); } } Wich will get the entity the player is looking and will damage it. But for some reason the attackEntityFrom method doesn't work Any idea of why this doesn't?
  19. Thanks for the answer, overriding the keyTyped method has solved the problem
  20. In my mod if a player is new to a world (first join of that player in a world) a GUI appear, let him choose a class. The problem is that the player can close this GUI and don't select a class, wich is something i want to avoid (so every player must have his class). This is the GUI class i use package com.rpg.gui; import java.io.IOException; import com.rpg.messages.PlayerClassMessage; import com.rpg.player.PlayerProperties; import com.rpg.utils.PlayerClasses; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import scala.swing.event.KeyPressed; public class GuiClassSelection extends GuiScreen{ private GuiButton tank; private GuiButton archer; private GuiButton assassin; private GuiButton support; public GuiClassSelection() { } @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { this.drawDefaultBackground(); super.drawScreen(mouseX, mouseY, partialTicks); } @Override public boolean doesGuiPauseGame() { return false; } @Override public void initGui() { tank = new GuiButton(0, this.width / 2 - 100, this.height / 2 - 54, "Tank"); archer = new GuiButton(0, this.width / 2 - 100, this.height / 2 - 24, "Archer"); assassin = new GuiButton(0, this.width / 2 - 100, this.height / 2 + 24, "Assassin"); support = new GuiButton(0, this.width / 2 - 100, this.height / 2 + 54, "Support"); this.buttonList.add(tank); this.buttonList.add(archer); this.buttonList.add(assassin); this.buttonList.add(support); } @Override protected void actionPerformed(GuiButton button) throws IOException { PlayerProperties props = PlayerProperties.get(this.mc.thePlayer); int pClass = PlayerClasses.TANK.ordinal(); if(button == this.tank) { pClass = PlayerClasses.TANK.ordinal(); } if(button == this.archer) { pClass = PlayerClasses.ARCHER.ordinal(); } if(button == this.assassin) { pClass = PlayerClasses.ASSASSIN.ordinal(); } if(button == this.support) { pClass = PlayerClasses.SUPPORT.ordinal(); } props.sendToServer(new PlayerClassMessage(pClass)); this.mc.displayGuiScreen(null); if(this.mc.currentScreen == null) this.mc.setIngameFocus(); } } How can i make it unclosable (so the player can't close this GUI until a class is selected)?
  21. Yes, i send only a packet holding the new value, than in the handler the setMana function is called, setting the mana to the new value by doing this props.setMana(message.getValue()); But i assume this is wrong due to you response. So i should only send in the message the amount of mana to add/subtract, then in the handler calcualte the new mana amount (with controls and stuff) and only then call the setMana function to set the mana to the new value and send a packet to the client? Basically should i do this in the PlayerProperties public void setMana(int amount) { this.mana = amount; } public void addMana(int amount) { this.sendToServer(new ManaValue(amount)); } public void removeMana(int amount) { this.sendToServer(new ManaValue(-1 * amount)); } and this in the handler? @Override public IMessage onMessage(final ManaValue message, final MessageContext ctx) { IThreadListener thread = RPG.proxy.getListener(ctx); EntityPlayer player = RPG.proxy.getPlayer(ctx); if(player != null) { final PlayerProperties props = PlayerProperties.get(player); if(props != null) { thread.addScheduledTask(new Runnable() { @Override public void run() { int mana = props.getMana() + message.getValue(); if (mana > props.getMaxMana()) mana = props.getMaxMana(); if (mana < 0) mana = 0; props.setMana(mana); //packet } }); } } return null; }
  22. The function to change the mana value is called only in the ManaHandler. What i do is this public int getMana() { return this.mana; } public void setMana(int amount) { this.mana = amount; if (this.mana > this.maxMana) this.mana = this.maxMana; if (this.mana < 0) this.mana = 0; } public void addMana(int amount) { this.sendToServer(new ManaValue(this.mana + amount)); } public void removeMana(int amount) { this.sendToServer(new ManaValue(this.mana - amount)); } Every time i want to change the value (by adding or subtracting something) i send a packet on the server with the new amount of mana, then in the ManaHandler the setMana function is called to actually set the new value. What i miss is from server to client what should i send, because if i send the same message i think it will always call the setMana function (as it will return constantly in the handler)
  23. Yes, the player exist in ManaHandler (i put a breakpoint at the start of the onMessage method. If the player does not exist then the null check will be true and nothing will happen). So the onMessage method is running but looking at the properties that this method will get i see that the mana value is 95 (while in the event is printed as 100). So i guess that client and server handles different values, wich is not good. How can i sync them?
  24. Tried doing this package com.rpg.events; import com.rpg.messages.ManaValue; import com.rpg.player.PlayerProperties; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; public class PlayerJoin { @SubscribeEvent public void onPlayerJoin(PlayerLoggedInEvent event) { PlayerProperties props = PlayerProperties.get(event.player); if(props != null) { System.out.println(props.getMana()); props.sendToClient(new ManaValue(props.getMana())); if(props.isFirstJoin()) { props.setJoined(); } } } } The print return 100 but the bar is still at 95
  25. I've done the class to sendToClient in the tick method (since this is called only from the tickHandler when world.isRemote is false). public void tick() { this.ticks++; if (this.ticks == this.getManaRegenTimer() && this.mana < this.maxMana) { this.ticks = 0; this.addMana(5); this.sendToClient(new ManaValue(this.getMana())); } } In game the bar updates correctly but still when logs out and then re-login the bar goes to default value (95/100) EDIT: in the PlayerJoinEvent i've printed the mana value and it is 100, while the bar displays 95 @SubscribeEvent public void onPlayerJoin(PlayerLoggedInEvent event) { PlayerProperties props = PlayerProperties.get(event.player); if(props != null) { System.out.println(props.getMana()); if(props.isFirstJoin()) { props.setJoined(); } } } This event is registered as well
×
×
  • Create New...

Important Information

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