Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Everything posted by coolAlias

  1. Yes, you should create a specific package for your API classes, if any, so that you can declare it as an API by including a package-info.java file: @API(owner = "yourmodid", provides = "UniqueNameForAPI", apiVersion = "1.8-1.0") package yourmod.api; import net.minecraftforge.fml.common.API; This lets FML / Forge know that this is an API package so that it prioritizes making the classes in it available sooner rather than later when loading mods (at least that's how I understand it - may not be 100% correct). Whether you release that API package separately or include it in your mod is up to you; personally I tend to just include them with my mods, but if you plan on having lots of your own mods using the same API, it may be better to release it separately as a dependency, or you could shade it.
  2. Be aware, however, that if you do use a Constructor Reference as suggested, your mod will require Java 8 to run. I recently released an update to one of my mods and compiled it with Java 7 compatibility by accident and had several people report crashes - they were still using Java 6... Don't let that stop you, though. People should really update their Java installations, but it's worth noting.
  3. You can compile against jars in the /mods folder as well if you add them manually to your referenced libraries, whereas they will be added automatically when you run 'gradlew eclipse' if they are in the /libs folder. Unless gradle has had major upgrades, then whichever folder you put the mod binaries in (be they regular .jar or dev builds), you will need to also add them as dependencies in the build.gradle.
  4. If you extend EntityLivingBase, your entity's attack damage attribute should already include any modifiers from the held item. Just use what mobs use: float damage = (float)this.getEntityAttribute(SharedMonsterAttributes.attackDamage).getAttributeValue(); If you want to make sure, print out the damage to the console and try it with and without various items equipped.
  5. You don't use SimpleNetworkWrapper at all - use the vanilla packet: @Override public Packet getDescriptionPacket() { NBTTagCompound tag = new NBTTagCompound(); tag.setSomeValueType("someKey", someValue); return new S35PacketUpdateTileEntity(getPos(), 1, tag); } @Override public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity packet) { NBTTagCompound tag = packet.getNbtCompound(); this.someValue = tag.getSomeValueType("someKey"); } Only write and read the values you actually need to sync to the NBT tag that you send.
  6. ItemStack NBT data syncs only one way automatically: from server to client. So, if you make changes on the server (e.g. by sending a packet from the GUI), those changes will be visible on the client side as well.
  7. GUIs are CLIENT-side only, so any settings you change there are lost when the client closes. You need to save settings on the server, so you will need to send packets if you want the settings to be changed from client side. Also, I didn't actually look at the settings you are changing, but most settings should only be set server side anyway and usually you don't want to expose them client-side at all.
  8. Override #getDescriptionPacket and #onDataPacket in your TileEntity and write / read any data you need on the client side. This packet is sent automatically to clients when the chunk loads or your block / TE gets marked for an update.
  9. What Lex says is very true, but don't let that discourage you - translations can be very flexible with just a little bit of formatting, as they ultimately use the Java Formatter class: // Lang file: yourmod.item.name=%s %s // results in "Tin Plate" yourmod.metal.tin.name=Tin yourmod.component.plate.name=Plate // Item code: @Override public String getItemStackDisplayName(ItemStack stack) { // Make sure to use #translateToLocalFormatted and pass the translations for each component as an argument return StatCollector.translateToLocalFormatted(getUnlocalizedName() + ".name", StatCollector.translateToLocal("yourmod.metal.tin.name"), StatCollector.translateToLocal("yourmod.component.plate.name")); Of course, it's up to you to determine which metal and component to use in the translation, probably using some kind of Object retrieved from NBT. But anyway, then languages with different ordering rules can translate it like so: // taking advantage of Formatter syntax to re-order the arguments: yourmod.item.name=%2$s %1$s // results in "Plate Tin"
  10. If you want to modify an attribute based on equipped / held items, then Item#getAttributeModifiers is the method you want - you can return a multimap with as many attribute modifiers as you want, and they will be applied and removed accordingly. ItemSword provides an example that increases the player's attack damage, but it is easy to modify to apply it to max health instead. In your case especially, I would only use an event such as LivingUpdateEvent as an absolute last resort, though if you don't want the modifier to apply when held, then it may be necessary.
  11. If you want to find that type of list yourself, the easiest way is to just look at the Forge code. Events are found in several different packages: 1. net.minecraftforge.event - the most-often used events are here, e.g. most of the player events 2. net.minecraftforge.fml.common.gameevent - previously in the cpw package, this is most known for TickEvents and has a few PlayerEvents as well 3. net.minecraftforge.common - look at the various 'Hook' classes to see how/where the events are actually used, or open the Call Hierarchy on an event's constructor; this is the surest way to determine which event bus to use, though in 1.8.9 I believe the event buses have all been combined into one.
  12. Finally decided to update to the latest Forge for 1.8 and have hit a snag: I can no longer successfully compile the mod. It seems some things have changed with Gradle, e.g. including a 'task sourceJar' in the build.gradle results in a failure due to it already existing, whereas it didn't before. Anyway, here is my error message: Execution failed for task ':retromapReplacedMain'. > filename net\minecraft\entity\DirtyEntityAccessor.java found package net\minecraft\entity->net/minecraft/entity but no class map for null I'm not sure if the forward- vs. back-slashes is significant - I am on a Windows machine. I've tried changing various things in my build.gradle and running gradlew clean to no avail. Here is the original build.gradle that works (on a VERY outdated version of Forge...), and here is the new one that is not working: Any ideas?
  13. I prefer to use the Material to check: if (!block.getMaterial().blocksMovement()) { // not a solid block, so go ahead and teleport if that's what you want }
  14. You've got some weird stuff going on: if (!world.isRemote) { // this means you are on the server side NameHeldStackGUI nameGui = new NameHeldStackGUI(); // GUI classes are typically CLIENT-side only Minecraft.getMinecraft().displayGuiScreen(nameGui); // Minecraft is DEFINITELY client-side only } Furthermore, if you are relying on that GUI to do something, such as set data in the ItemStack's NBT, well that won't work without sending packets. NBT data should only be set on the server side. Just FYI, most of the NBTTagCompound methods return the equivalent of false if the tag does not exist, so: if (nbtTagCompound.getBoolean("bound")) will only return true if the tag has the boolean key "bound" and that key is true, meaning you often don't need to check `if (tag.hasKey("bound"))` - it is implicit in the getter.
  15. Calling the GL translate method with the 2nd, 3rd, and 4th parameters (x, y, and z) is also very important - if you don't, you very likely will not see anything at all.
  16. The reason KeyInputEvent wouldn't work, if you haven't figured it out already, is that it only fires when a key is pressed or released - since the player is AFK, obviously that's impossible TickEvents, however, fire each tick no matter what the player is doing, which part of the reason Choonster chose the event he did.
  17. You're using the wrong constructor - most projectiles have a constructor that takes an EntityLivingBase, i.e. the one that is shooting the projectile, and will automatically calculate the trajectory and velocity for you. Some also have a constructor that takes the target entity which is useful for mobs shooting at players. Unfortunately, EntityFireball is a bit odd in the projectile world, as Draco pointed out, but you can still use a constructor that takes more arguments for a better result. Blazes, Ghasts, etc. typically pass in the difference between the target's position and their own. From the Ghast: double dx = this.targetedEntity.posX - this.posX; double dy = this.targetedEntity.boundingBox.minY + (double)(this.targetedEntity.height / 2.0F) - (this.posY + (double)(this.height / 2.0F)); double dz = this.targetedEntity.posZ - this.posZ; EntityLargeFireball entitylargefireball = new EntityLargeFireball(this.worldObj, this, dx, dy, dz); That will create a fireball heading towards the target's current position with appropriate velocity and acceleration. Of course there are a couple extra adjustments that the ghast and such make to the position before spawning it to make sure it doesn't immediately collide with themselves, but you can see that in the code.
  18. Hotbar slots are 0 to 8, so (i = 0; i < 9).
  19. I've always hated the factory method... it does have certain use cases, but I think it is way overused, such as in this case. I mean really, what was wrong with creating the new instance yourself? Now you have to create a factory instance to create your render instance, gaining what? Nothing, imo. Here's a fun read about that
  20. In my opinion, you would be better off trying it first, and asking questions later
  21. I note quite frequently throughout the tutorial that the packet code is old, and link to more recent packet handling tutorials, with a big note: I considered updating the actual packet code in the tutorial, but I consider it medicine against copy / pasting. I can't help it if one cannot be bothered to actually read the tutorial.
  22. The entity UUID will NOT change, but the id from #getEntityID will. However, the entities will not exist until the chunk that they are in is loaded, so they will likely be null for a while after loading the game. One way around that is to store their last known coordinates and load that chunk (if not already loaded) when searching for them, but even that's not foolproof - the entity may have moved, died, etc.
  23. Exactly, so store the list of entities that can be called in the Player's IEEP, and use that list to populate whatever GUI you open when using the radio item. Just because you use the list with the Item doesn't mean it has to be stored somewhere in the Item.
  24. Why do you need to store the list of entities in the radio? I would suggest instead storing the list in the Player's IEEP - then whenever they use a radio, ANY radio, they can call their mercenaries.
  25. Indeed, that looks fine. The only thing I can think of, completely untested, is that your call to the LanguageRegistry is borking things: LanguageRegistry.instance().addStringLocalization("entity.jolo:Monster.name", "en_US", "Monster"); Ever since at least 1.6.4, you should NOT be using the LanguageRegistry directly, but instead creating an en_US.lang file in your /resources/assets/yourmodid/lang folder - this is what handles all of the translations, e.g.: entity.yourmodid.monster.name=Monster I recommend you use all lowercase for every unlocalized name, be it Entity, Block, Item, or otherwise. Note that you do not need to prepend the entity name with your modid, that happens automatically, and the registration method requires an integer index, not your MOD_ID: int index = 0; // start at 0 and add 1 for each custom entity registered EntityRegistry.registerModEntity(EntityMonster.class, "monster", index++, Jolo.instance, 80, 3, false);
×
×
  • Create New...

Important Information

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