Jump to content

gibraltar

Members
  • Posts

    14
  • Joined

  • Last visited

Converted

  • Gender
    Undisclosed
  • Personal Text
    I am new!

gibraltar's Achievements

Tree Puncher

Tree Puncher (2/8)

0

Reputation

  1. These compasses will fit into a bigger story in the mod, but I do like the idea of compasses found in strongholds (the only place in vanilla where they can be found) pointing back to the stronghold. As for stackability, once a compass has the NBT tags that tell it where to point, then only other compasses with the exact same tags can be stacked with it. Which makes sense for my purposes.
  2. Good points, Hugo. I think I've got it working now, so I can play around with different ways to activate the compass. Regardless, I like the way you're thinking when it comes to PvP.
  3. Dang, Draco, you are always so quick to help. It's awesome. I suspected it was something like this. So I guess the next question is where would be a good place, server side, to set the NBT tags. I could do it in ItemCraftedEvent, because there is a player associated with it. What about when a player pulls one of these compasses from a chest (put there by a loot table), or gets one via a villager trade?
  4. In http://www.minecraftforge.net/forum/index.php?topic=43848.0 I asked about a compass that points to the players personal spawn. Thanks to the pointers I got that working with packets to get the correct spawn point. Now I'm going a slightly different direction, and want the compass to point to the players spawn when it is crafted, and keep pointing to that original location, even when the player's spawn changes. Currently, when the spawn NBT tags aren't on the compass' item stack, the code below asks for the player spawn, gets it, then sets it as NBT tags on the item stack. The problem is that when the player opens their inventory, the compass doesn't have the NBT tags, so they are retrieved again (possibly updating them) and set on the item stack again. I've done some digging and cannot see how the NBT tags are being removed from the item stack when you open your inventory. Note that a similar thing happens when you pick the compass up and drag it to a new inventory slot. Yet, as far as I can tell, whenever an ItemStack is copied, the associated NBT tags are copied as well. public class ItemPersonalCompass extends Item { public ItemPersonalCompass() { addPropertyOverride(new ResourceLocation("angle"), new IItemPropertyGetter() { @SideOnly(Side.CLIENT) double rotation; @SideOnly(Side.CLIENT) double rota; @SideOnly(Side.CLIENT) long lastUpdateTick; @SideOnly(Side.CLIENT) public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) { if (entityIn == null && !stack.isOnItemFrame()) { return 0.0F; } else { boolean flag = entityIn != null; Entity entity = flag ? entityIn : stack.getItemFrame(); if (worldIn == null) { worldIn = entity.worldObj; } BlockPos destinationPos = getCompassSpawn(stack); if (destinationPos == null) { FMLLog.info("getting compass spawn"); destinationPos = FindYourWayChallenge.getPlayerSpawn(); if (destinationPos == null) { return 0F; } else { FMLLog.info("setting compass spawn"); setCompassSpawn(stack, destinationPos.getX(), destinationPos.getZ()); } } double d0; if (destinationPos != null) { double d1 = flag ? (double) entity.rotationYaw : getFrameRotation((EntityItemFrame) entity); d1 = d1 % 360.0D; double d2 = getPosToAngle(worldIn, entity, destinationPos); d0 = Math.PI - ((d1 - 90.0D) * 0.01745329238474369D - d2); } else { d0 = Math.random() * (Math.PI * 2D); } if (flag) { d0 = wobble(worldIn, d0); } float f = (float) (d0 / (Math.PI * 2D)); return MathHelper.positiveModulo(f, 1.0F); } } @SideOnly(Side.CLIENT) private double wobble(World p_185093_1_, double p_185093_2_) { if (p_185093_1_.getTotalWorldTime() != lastUpdateTick) { lastUpdateTick = p_185093_1_.getTotalWorldTime(); double d0 = p_185093_2_ - rotation; d0 = d0 % (Math.PI * 2D); d0 = MathHelper.clamp_double(d0, -1.0D, 1.0D); rota += d0 * 0.1D; rota *= 0.8D; rotation += rota; } return rotation; } @SideOnly(Side.CLIENT) private double getFrameRotation(EntityItemFrame itemFrame) { return (double) MathHelper.clampAngle(180 + itemFrame.facingDirection.getHorizontalIndex() * 90); } @SideOnly(Side.CLIENT) private double getPosToAngle(World world, Entity entity, BlockPos blockpos) { return Math.atan2((double) blockpos.getZ() - entity.posZ, (double) blockpos.getX() - entity.posX); } }); setUnlocalizedName("compass_personal"); setCreativeTab(CreativeTabs.TOOLS); setRegistryName(Reference.MOD_PREFIX + "compass_personal"); GameRegistry.register(this); GameRegistry.addRecipe(new ItemStack(this), " I ", "IRI", " I ", 'I', Items.IRON_INGOT, 'R', Items.REDSTONE); ModelLoader.setCustomModelResourceLocation(this, 0, new ModelResourceLocation("iberia:compass_personal", "inventory")); } public void setCompassSpawn(ItemStack stack, int x, int z) { if (verifyNBT(stack) && !stack.getTagCompound().getBoolean("SpawnSet")) { FMLLog.info("setting spawn for compass: " + x + ", " + z); stack.getTagCompound().setBoolean("SpawnSet", true); stack.getTagCompound().setInteger("SpawnX", x); stack.getTagCompound().setInteger("SpawnZ", z); } } public BlockPos getCompassSpawn(ItemStack stack) { if (verifyNBT(stack) && stack.getTagCompound().hasKey("SpawnSet")) { return new BlockPos(stack.getTagCompound().getInteger("SpawnX"), 0, stack.getTagCompound().getInteger("SpawnZ")); } return null; } public boolean verifyNBT(ItemStack stack) { if (stack.func_190926_b()) { return false; } if (stack.getItem() != this) { return false; } else if (stack.getTagCompound() == null) { FMLLog.info("setting tag compound"); stack.setTagCompound(new NBTTagCompound()); } return true; }
  5. Ok, here's my current theory, after further investigation. The EntityPlayer that gets passed to the IItemPropertyGetter.apply is an AbstractClientPlayer and thus on the client side. I believe that EntityPlayer never has it's spawnChunk field updated when the player's spawn is set (that happens on the server), and the EntityPlayer object on the server side that does have it's spawnChunk set is never communicating that information to the client side. So it appears I need some way, given an AbstractClientPlayer, to ask the server for that player's bed location / spawnChunk. Once that's in place, I'll need a way of caching that info on the client side associated with the AbstractClientPlayer so I'm not asking for it every time we render a compass. I'll be investigating how to do that next, but any tips/pointers to get me started would be awesome.
  6. Right, I'm setting up the IItemPropertyGetter the same way it is set up in the vanilla compass class, so I feel good about that. But I think there must be some difference between the EntityPlayer being passed into the apply method and the EntityPlayer being passed to the PlayerSetSpawn event
  7. I've written a compass that I believe should point to your personal spawn point, if it's been set. It looks a lot like the regular compass code, but instead of pointing to world spawn it gets the bed location for the current user and points to that. The issue I'm seeing is that when I sleep in a new place, the compass doesn't start pointing to the new location. But I've checked that the player's spawn is changing, and the same method, getBedLocation returns a different value when called within other events, so I'm not sure what the problem is. Any help would be appreciated. public class ItemPersonalCompass extends Item { public ItemPersonalCompass() { addPropertyOverride(new ResourceLocation("angle"), new IItemPropertyGetter() { @SideOnly(Side.CLIENT) double rotation; @SideOnly(Side.CLIENT) double rota; @SideOnly(Side.CLIENT) long lastUpdateTick; @SideOnly(Side.CLIENT) public float apply(ItemStack stack, @Nullable World worldIn, @Nullable EntityLivingBase entityIn) { if (entityIn == null && !stack.isOnItemFrame()) { return 0.0F; } else { boolean flag = entityIn != null; Entity entity = flag ? entityIn : stack.getItemFrame(); if (worldIn == null) { worldIn = entity.worldObj; } BlockPos destinationPos = new BlockPos(0, 0, 0); if (entity instanceof EntityPlayer) { destinationPos = ((EntityPlayer) entity).getBedLocation(0); if (destinationPos == null) { return 0; } } else { return 0F; } double d0; if (destinationPos != null) { double d1 = flag ? (double) entity.rotationYaw : getFrameRotation((EntityItemFrame) entity); d1 = d1 % 360.0D; double d2 = getPosToAngle(worldIn, entity, destinationPos); d0 = Math.PI - ((d1 - 90.0D) * 0.01745329238474369D - d2); } else { d0 = Math.random() * (Math.PI * 2D); } if (flag) { d0 = wobble(worldIn, d0); } float f = (float) (d0 / (Math.PI * 2D)); return MathHelper.positiveModulo(f, 1.0F); } } @SideOnly(Side.CLIENT) private double wobble(World p_185093_1_, double p_185093_2_) { if (p_185093_1_.getTotalWorldTime() != lastUpdateTick) { lastUpdateTick = p_185093_1_.getTotalWorldTime(); double d0 = p_185093_2_ - rotation; d0 = d0 % (Math.PI * 2D); d0 = MathHelper.clamp_double(d0, -1.0D, 1.0D); rota += d0 * 0.1D; rota *= 0.8D; rotation += rota; } return rotation; } @SideOnly(Side.CLIENT) private double getFrameRotation(EntityItemFrame itemFrame) { return (double) MathHelper.clampAngle(180 + itemFrame.facingDirection.getHorizontalIndex() * 90); } @SideOnly(Side.CLIENT) private double getPosToAngle(World world, Entity entity, BlockPos blockpos) { return Math.atan2((double) blockpos.getZ() - entity.posZ, (double) blockpos.getX() - entity.posX); } }); setUnlocalizedName("compass_personal"); setCreativeTab(CreativeTabs.TOOLS); setRegistryName(Reference.MOD_PREFIX + "compass_personal"); GameRegistry.register(this); GameRegistry.addRecipe(new ItemStack(this), " I ", "IRI", " I ", 'I', Items.IRON_INGOT, 'R', Items.REDSTONE); ModelLoader.setCustomModelResourceLocation(this, 0, new ModelResourceLocation("iberia:compass_personal", "inventory")); } }
  8. It looks like modifying the item usage duration in LivingEntityUseItemEvent.Start doesn't properly change the resulting animation, e.g. food doesn't show as being eaten during the whole duration, if you're modifying it for built in item types. I tried doing this for food, so that it takes longer to eat when wearing certain armor, but instead, you get no animation for a while, then the animation for the regular usage time. I noticed that AppleCore has a solution at https://github.com/squeek502/AppleCore/blob/0a5a53d501ae5737bd50f7e332a1e5cbb4bb0c08/java/squeek/applecore/asm/module/ModuleFoodEatingSpeed.java. Would it make sense to embed a similar solution into Forge itself?
  9. Thanks for the ideas, everyone. It looks like onArmorTick happens once for each piece of armor you're wearing, which is overkill for what I'm doing. OnPlayerTick it is! And I'll take a look at making a PR as well.
  10. I would like to make it so that if the player walks on farmland while wearing certain armor, that the farmland reverts to dirt, trampling the crops. I want something like onEntityWalking, but it looks like overriding the farmland block would be nigh impossible, because of all the places in the Minecraft code that refers to it via Blocks.FARMLAND rather than using instanceof. Another option would be to add an EntityWalkingEvent to Forge, but that may be overkill, plus it would require waiting however long it takes to get the PR approved and into Forge. Am I missing other options?
  11. Thanks for the suggestions, guys. I dove into the Forge code yesterday and came up with a PR that adds the event I want: https://github.com/MinecraftForge/MinecraftForge/pull/3373. Hopefully, it will make it into the product soon. Feels good to give a little back (and also scratch my own itch).
  12. The reason I'm asking about events is because I've already gone down the route of overriding the ContainerEnchantment class. To do what I'm trying to accomplish, I'd almost need to copy all of the code over (not super maintainable going forward), because I need to make minor changes inside the onCraftMatrixChanged method. And not at the beginning or end of it, or I could just call the base implementation. They have to fit in between the loop that calculates the enchant levels and the loop that uses those to get the actual enchantments. Unfortunately, it calls private methods and uses private fields, which won't be available. Making the whole thing quite hacky, if I can even get it to work.
  13. I'd like to modify the enchantment levels offered in each slot (not the enchantments themselves), based on the player (NBT tags, or items they are carrying, etc.). After looking through the ContainerEnchantment and EnchantmentHelper classes, it appears the only way to do that currently would be with IClassTransformer. But that's a no-no. So, is there a different way to do this that I'm missing? If not, how would I go about adding an event to forge to make this possible? I'd be happy if the normal calculation occured, and I could just modify the levels before the actual enchantments are calculated based on the level.
  14. I'm trying to make some minor asm modifications to ContainerEnchantment, or alternatively, to EnchantmentHelper. But though my transform method is being called, it's not being passed either of those classes. Is there a good reason for that? Or do I need to do something to get Forge to call transform with one of those classes? Thanks in advance!
×
×
  • Create New...

Important Information

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