Jump to content

shadowmage4513

Forge Modder
  • Posts

    157
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by shadowmage4513

  1. It is firing once on the client, and once on the server. You will need to add some world.isRemote checks and only run the action on the proper side. Also, I believe that the container workbench has some code in it to auto-close if the player is out of range of the workbench, which is set via the (0,0,0) you are passing in...so unless the player is standing at 0,0,0 or near to it, it will close shortly after opening. vanilla workbench code that causes the closing in ContainerWorkbench: public boolean canInteractWith(EntityPlayer par1EntityPlayer) { return this.worldObj.getBlock(this.posX, this.posY, this.posZ) != Blocks.crafting_table ? false : par1EntityPlayer.getDistanceSq((double)this.posX + 0.5D, (double)this.posY + 0.5D, (double)this.posZ + 0.5D) <= 64.0D; }
  2. You cannot have a block with a hitbox larger than 1 block -- you will need to use tile entities and a multiblock structure to accomplish what you are trying to do. This is due to the way minecraft looks up the hitbox -- it has no way of knowing that when you are looking at a given X,Y,Z that you really want to pull up and use the hitbox from the block located at X,Y-1,Z.
  3. #1: In your run-configurations, add the following to the 'Program Arguments': --username <your_desired_name_here> ^^ Keep in mind, that login is not authenticated, and you will not be able to login to actual live remote servers with the development client. (although it will work if the server is set to offline mode / not authenticate) #2 I'm glad you bring this up, because this has been bugging me as well. I was thinking there was something I might have not done properly in my network code, but it does seem to be related to a thread-race during startup. So, I'm not sure if it is a 'know issue' to the forge-devs, but it is certainly a known issue amongst some of the other mod developers.
  4. I would examine the changes made to zombies that allows them to path up to 40 blocks or whatever. Essentially the problem is not the 'finding' the player, it is the pathfinding -- most mobs pathfinding is hard-coded to only go out 16 blocks. Hence, check out the zombie, as Mojang themselves have upped that one to a higher distance.
  5. Example code to locate all direct neighbors of a tile-entity. Lots of ways to do this, including just manually checking each x/y/z +/- set. But I like loops, so this is a simple loop After calling the method, cachedNeighbors will contain references to any nearby tile entities, or null if none. Each index corresponds to a forge-direction (north, south, east, west, up, down..though not necessarily in that order). TileEntity[] cachedNeighbors = new TileEntity[6]; public void updateNeighbors() { ForgeDirection d; int x, y, z; TileEntity te; for(int i = 0; i <6 ;i++) { d = ForgeDirection.values()[i]; x = xCoord + d.offsetX; y = yCoord + d.offsetY; z = zCoord + d.offsetZ; te = worldObj.getTileEntity(x, y, z); cachedNeighbors[d.ordinal()]=te; } } You can use the above without the caching as well...just put your operational code in instead of putting the te in the array. To check a specific side, after the cache has been updated, you could query such as if(cachedNeighbors[ForgeDirection.NORTH.ordinal]!=null) { //do something with the north-neighbor }
  6. You will need to implement your own ItemBlock class to register with your block. Your custom class can then override the addInformation method from Item. E.G.: Block class: public class ItemBlockStructureBuilder extends ItemBlock { public ItemBlockStructureBuilder(Block p_i45328_1_) { super(p_i45328_1_); } @Override @SideOnly(Side.CLIENT) public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4) { String name = "corrupt_item"; if(par1ItemStack.hasTagCompound() && par1ItemStack.getTagCompound().hasKey("structureName")) { name = par1ItemStack.getTagCompound().getString("structureName"); } par3List.add("DEBUG- struct name: "+name); } } Item/block registry (in a load method in an item-loader class, called during mod-pre-init): AWBlocks.builderBlock = new BlockStructureBuilder("structure_builder_ticked"); GameRegistry.registerBlock(AWBlocks.builderBlock, ItemBlockStructureBuilder.class, "structure_builder_ticked");//register your itemBlock with the block
  7. Method to find the block that a player is looking at: -- mostly adapted/copied from some old code in Item class so that it could be accessed outside of an item. You can change reachLength to the maximum length you want to check. If nothing is found in that range, it will return null. If you don't want to hit entities, you can remove that section entirely leaving only the blocks portion. offset parameter is if you want to offset for side hit, such as if you are placing a block (get the block clicked IN instead of the one clicked ON) BlockPosition is a simple tuple/triplet class --- three int fields, x, y, z, and some utility methods. Change this to your prefferred return data-type (its actually been awhile since I've looked at that code...no idea what scaleFactor was supposed to do...but the rest should be fairly obvious) /** * will return null if nothing is in range * @param player * @param world * @param offset * @return */ public static BlockPosition getBlockClickedOn(EntityPlayer player, World world, boolean offset) { float scaleFactor = 1.0F; float rotPitch = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * scaleFactor; float rotYaw = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * scaleFactor; double testX = player.prevPosX + (player.posX - player.prevPosX) * scaleFactor; double testY = player.prevPosY + (player.posY - player.prevPosY) * scaleFactor + 1.62D - player.yOffset;//1.62 is player eye height double testZ = player.prevPosZ + (player.posZ - player.prevPosZ) * scaleFactor; Vec3 testVector = Vec3.createVectorHelper(testX, testY, testZ); float var14 = MathHelper.cos(-rotYaw * 0.017453292F - (float)Math.PI); float var15 = MathHelper.sin(-rotYaw * 0.017453292F - (float)Math.PI); float var16 = -MathHelper.cos(-rotPitch * 0.017453292F); float vectorY = MathHelper.sin(-rotPitch * 0.017453292F); float vectorX = var15 * var16; float vectorZ = var14 * var16; double reachLength = 5.0D; Vec3 testVectorFar = testVector.addVector(vectorX * reachLength, vectorY * reachLength, vectorZ * reachLength); MovingObjectPosition testHitPosition = world.rayTraceBlocks(testVector, testVectorFar, true); /** * if nothing was hit, return null */ if (testHitPosition == null) { return null; } Vec3 var25 = player.getLook(scaleFactor); float var27 = 1.0F; List entitiesPossiblyHitByVector = world.getEntitiesWithinAABBExcludingEntity(player, player.boundingBox.addCoord(var25.xCoord * reachLength, var25.yCoord * reachLength, var25.zCoord * reachLength).expand(var27, var27, var27)); Iterator entityIterator = entitiesPossiblyHitByVector.iterator(); while (entityIterator.hasNext()) { Entity testEntity = (Entity)entityIterator.next(); if (testEntity.canBeCollidedWith()) { float bbExpansionSize = testEntity.getCollisionBorderSize(); AxisAlignedBB entityBB = testEntity.boundingBox.expand(bbExpansionSize, bbExpansionSize, bbExpansionSize); /** * if an entity is hit, return its position */ if (entityBB.isVecInside(testVector)) { return new BlockPosition(testEntity.posX, testEntity.posY, testEntity.posZ); } } } /** * if no entity was hit, return the position impacted. */ int var42 = testHitPosition.blockX; int var43 = testHitPosition.blockY; int var44 = testHitPosition.blockZ; /** * if should offset for side hit (block clicked IN) */ if(offset) { switch (testHitPosition.sideHit) { case 0: --var43; break; case 1: ++var43; break; case 2: --var44; break; case 3: ++var44; break; case 4: --var42; break; case 5: ++var42; } } return new BlockPosition(var42, var43, var44); }
  8. If done properly, all synchronization is done automatically by the Container. If all you are doing is displaying inventory slots / allowing players to move items around in them, there should be nothing extra that you need to do beside setup your container correctly. Also, when you call openGUI, make sure you are calling that from the SERVER side, or it will only open the container on the client...and then you get desynch. So on your entity-interact method, have it check for if(!worldObj.isRemote){//call FML.openGUI method} I'll browse through your code to see if I can spot any problems, but at first glance, your container/etc _should_ be setup properly. Are you manipulating the entities inventory from anywhere else, or accidentally changing things client-side? (essentially, the inventory only exists server-side...the only time the client has a copy is when the GUI is open...so trying to manipulate the inventory from client side from outside of the container/gui won't work very well) Sorry...just trying to list the problems/solutions that I encountered when first working with this stuff...I know it took me quite a while to get my first entity-based inventory working properly. I would also try and eliminate whatever mapping you were using for entity-IDs. I tried a similar system originally, and found it to be very error prone. (first of all, the entity-id's are not persistent...and second, they sometimes don't match, especially when an entity is first loaded from disk). The best way I found was just to use the information directly from the entity when needed, and then retrieve the entity from world.getEntityByID. (Just mentioning this, as I had some desynch issues with my first attempts at gui/inventory because I was retreiving the wrong entity on either the client or server side....)
  9. You don't need a tile-entity at all. In fact, that is the wrong way to handle this completely. Tile entities are for blocks. For an Entity with an inventory, you need only make your entity implement IInventory (the same way that you would make a tile-entity implement IInventory). After you get all the inventory methods setup properly in the entity, you need a way to reference the entity to open the proper inventory. When calling to open a GUI, forge gives you three int params to use, x, y, and z. Use one/two of these to send the entity-id of the entity that has its inventory opened. Retrieve the proper entity on the other side by calling world.getEntityByID(int id). (In the following example entity, I have bridged the inventory functions to an internal inventory object instead of implementing the inventory directly in the entity) Example entity-class public class VehicleBase extends Entity implements IInventory { //missing inventory field, as it is a custom class -- use your own implementation of IInventory @Override public int getSizeInventory() { return inventory.getSizeInventory(); } @Override public ItemStack getStackInSlot(int i) { return inventory.getStackInSlot(i); } @Override public ItemStack decrStackSize(int i, int j) { return inventory.decrStackSize(i, j); } @Override public ItemStack getStackInSlotOnClosing(int i) { return inventory.getStackInSlotOnClosing(i); } @Override public void setInventorySlotContents(int i, ItemStack itemstack) { inventory.setInventorySlotContents(i, itemstack); } @Override public String getInvName() { return inventory.getInvName(); } @Override public boolean isInvNameLocalized() { return inventory.isInvNameLocalized(); } @Override public int getInventoryStackLimit() { return inventory.getInventoryStackLimit(); } @Override public void onInventoryChanged() { inventory.onInventoryChanged(); } @Override public boolean isUseableByPlayer(EntityPlayer entityplayer) { return inventory.isUseableByPlayer(entityplayer); } @Override public void openChest() { } @Override public void closeChest() { } @Override public boolean isItemValidForSlot(int i, ItemStack itemstack) { return inventory.isItemValidForSlot(i, itemstack); } } Server-side gui handler (note how I retrieve the entity by entity ID from the (x) parameter) @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { VehicleBase vehicle; TileEntity te; switch(ID) { case VEHICLE_DEBUG: vehicle = (VehicleBase)world.getEntityByID(x); if(vehicle!=null) { return new ContainerVehicle(player, vehicle, vehicle); } return null; case PERFORMANCE: return new ContainerDebugInfo(player); } return null; } Client-side gui handler @Override public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { VehicleBase vehicle; switch(ID) { case VEHICLE_DEBUG: vehicle = (VehicleBase)world.getEntityByID(x); if(vehicle!=null) { return new GuiVehicleInventory(new ContainerVehicle(player, vehicle, vehicle)); } return null;//TODO make/set gui & container.. } return null; } Code that is called to open the GUI (from right-click on entity)(note entityID sent as the 'x' coordinate) FMLNetworkHandler.openGui(player, AWCore.instance, GUIID, world, entityID, 0, 0);
  10. I had to change from 'authors' to 'authorsList' sometime after 1024. Here is what works for me: "authorList": ["shadowmage45"],
  11. try enabling lighting. It appears as if all of your blocks are rendering @ full brightness. try placing: GL11.glEnable(GL11.GL_LIGHTING) before you do your item-stack rendering
  12. Yes, Draco18s, that is pretty much exactly what I would be doing Perhaps I will investigate doing a core-mod for this (its about time to learn), or maybe even see how hard making an event for it for Forge would be. I seemed to remember an explosion event mentioned in the github issues tracker quite awhile back, but apparently it didn't make it in.
  13. Hi all, I am looking into an Explosion Event -- if one exists? (I sure couldn't fine one in any relases from 1.5.x -> 1.7.2) If not, is anyone aware of a (clean) method to intercept TNT explosions (preferably ALL explosions)? My goal is to have blocks/entities that offer limited 'protection' or 'reinforcement' of other blocks in their range (as part of a Siege based PVP system). I have the system working exceptionally well with the use of block-break events....but I cannot find how/where to intercept explosions? The closest I've come is a tick-handler / onUpdate method to examine all nearby entities and see if there is a TNT or creeper about to explode and cancel / kill / remove it if it would effect the reinforced area at all. Neither a clean solution, nor quite what I'm looking for. Ideally the explosion would still have normal effects outside of the reinforced area, whereas this solution entirely kills the explosion. The other solution that I thought of would be constantly scanning/validating all of the blocks that are supposed to be 'reinforced' and replacing them if they were not removed via a block-break event -- but this can cause all sorts of headaches with non-loaded chunks, other mods replacing blocks outside of the events, and is terribly inefficient. Any ideas? Thanks in advance, Shadowmage
  14. I've always used the blend function of: GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); I'm not an expert, and am not really sure of the difference between the two, but that is the function that has worked well for me in all of my code that deals with transparency.
  15. Thanks much -- I'll give this a go. I figured there was probably something basic I was overlooking.
  16. Has anyone found out how to specify the runtime directory to be used when launching MC/debug from eclipse? The current/default setup seems to run in the base directory of wherever I have setup the forge install at....which creates a bunch of extra ...stuff... in the base repo directory. For example, after running MC server, I get the /worlds directory. After running either client/server, I get the /config directory, and a bunch of log files. All of these appear in the same base directory as my build.gradle file. Is there any way to specify a separate runtime directory to use when launched from an IDE? So I could have a /runtime or /debug folder in my repo that held all of that stuff? (Much easier to add a single directory to .gitignore than a ton of random files -- and it also just seems silly to clutter up my base folder with those files in the first place) Anyone had any luck in figuring this out, is there something I missed, or perhaps my installation is not setup properly? Thanks, Shadowmage
  17. Well...a bit more playing around, research, reading..experimenting, and I've found the solution. Essentially, my earlier attempts were correct, however there is no run-time error to tell you that you are missing imports. Hell, there was nothing to let me know that gradle could even use imports. so...anyway, if anyone is curious, here is the code: (yes, I put open braces on new-lines....which I think can also mess with gradle a bit, hence the single task with the broken brace) import org.apache.tools.ant.filters.ReplaceTokens buildscript { repositories { mavenCentral() maven { name = "forge" url = "http://files.minecraftforge.net/maven" } } dependencies { classpath 'net.minecraftforge.gradle:ForgeGradle:1.0-SNAPSHOT' } } allprojects { apply plugin: 'forge' minecraft { version = "1.6.4-9.11.1.964" } version = project.version group = "shadowmage" // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = "ancientwarfare" } sourceSets.main { java { srcDirs 'src' } resources { srcDirs 'resources' } } compileJava.source = sourceSets.main.java task updateVersion(type:Copy){ from('src') { exclude 'mcmod.info' } into 'build/sources/java' filter(ReplaceTokens, tokens: [VERSION: project.version]) } compileJava.dependsOn updateVersion processResources { from(sourceSets.main.java.srcDirs) { include 'mcmod.info' expand ('version':project.version) expand ('mcversion':project.minecraft.version) } from(sourceSets.main.resources.srcDirs) { } } Edit: Apparently this is still not entirely correct (it is not compiling the sources...I've probably specified build directory improperly), and I've got a bit of updating to do, but the version token replacement bit _does_ work. Further Edit: build-file code has been fixed to actually include the updated sources for compilation there is probably a better way to do this -- hopefully someone can point it out...but for now, this solution works. next up: how to update a build number from build-script. research tells me again to use an ant task. I'll let you all know how it goes.
  18. Hi all, I have previously been using an ant-build script for compiling of my mod. It used a technique that I learned from Buildcraft to replace the version number in the mod source (in the .java files) with the version number provided to the build system (through a properties file, command line, etc). It would replace any version tokens found in the source with the intended version number from the build environment. This simplified several things, as I only had to update my version number in a single place to have it propagate/replaced across to the various Mod classes/config classes as well as the mcmod.info file. Has anyone found a similar solution using Gradle? The default-shipped build.gradle file includes the code for updating the mcmod.info file (I've even got it loading the version number from an external properties file as it was for ant), but I can't seem to find a way to adapt the same code to work on source-files? (the processResources task is apparently called _after_ compilation, so at that step it is too late to find/replace tokens) All of the google research that I was able to do suggested two things A: That you shouldn't dynamically replace strings in source, but should instead load the strings into the program from a properties file at runtime -- unfortunately this cannot be done for the Mod version number, as it is declared as a final field -- it HAS to exist at compile-time, it cannot be delayed until runtime. So either I manually update version number across multiple files, or continue doing it with a build script in one fashion or another. The other suggestion B: Was to use an ant.task from within gradle to accomplish the same thing. Okay..great..pretty sure I could figure out how to get that working -- but where precisely to put that new task, and how to link it into the existing build file? (I'm thinking I should be able to declare a new task, and tell gradle that the compileJava task depends on the new one, but I'm a bit lost on...well..the entire gradle environment/language, and all the documentation I can find is so far abstracted from what I am trying to accomplish that I cannot draw any parallels to learn from). Anyone have experience with this stuff in gradle / figured out how to duplicate this simple functionality in gradle?
  19. You are close try something like: for(int i = 0; i <= MoChickens.eggNum; i++) { System.out.println("Class " + MoChickens.egg + " has been added"); Class<? extends Class> type = MoChickens.egg; Entity newEntity = type.getDeclaredConstructor(World.class).newInstnance(par2EntityPlayer.worldObj); //you will need to surround this with try/catch, as the reflection method can/will throw multiple instantiation exceptions }
  20. Sorry, I don't have an answer, I was just writing to add that I, too, am curious as to how this can be done. I have needed this ability at various points to track down strange issues or to more-closely examine how the base MC source works. It would be a shame to have to set up an entire Forge/FML dev environment just to add some temporary debug output to a base-class.
  21. Depending upon the mob (if it is vanilla or not), you may be able to simply remove the AI tasks from its AI, or insert/overwrite with your own tasks. This could be done with the EntityJoinWorld event. Another method might be to handle the LivingSetAttackTargetEvent, cancelling the target/overwriting the target for that entity. (Haven't played with this one myself...so..it _might_ be viable) A bit of a hackier method would be to use a tick-handler and examine entities near players, and remove/reset their AI target. There may well be other methods as well, as this is not something that I've looked into very much. Edit: these are methods that should work fine with vanilla entities. Handling mod entities will be hit-and miss depending upon whether they call the appropriate events and/or use the vanilla AI system.
  22. Ehh, depth-test was worth a try For the brightness, you might try disabling lighting if you haven't already. It sounds strange that turning lights off makes things brighter, but openGL works in some strange ways sometimes (rather, it is trying to apply the global/local/currently bound lighting level to every texture that is rendered)
  23. Have you tried disabling depth-testing, as it sounds like you are wanting to do? e.g. GL11.glDisable(GL11.GL_DEPTH_TEST) at the start of rendering and then GL11.glEnable(GL11.GL_DEPTH_TEST) afterwards to reset the flag for others' rendering This should make it render the particles regardless of what is 'in front' of them, but then it is render-order dependant (anything rendered afterwards will draw over the particles)
  24. Create a class implementing IItemRenderer register it with: MinecraftForgeClient.registerItemRenderer(int itemID, IItemRenderer renderer);. your IItemRenderer class will have several methods to define, one of which is the important one: @Override public void renderItem(ItemRenderType type, ItemStack item, Object... data) { //do your render stuff here...you will need to render your own icon, use openGL draw calls to render the damage-bars. //you can render...well...pretty much anything here } the Object... data input array contains information such as the World, delta-tick time...etc...it varies by render-type. the other methods help determine _when_ to use the custom renderer.
  25. Hi all.. Working on setting up a 1.7x dev environment. Got everything downloaded, eclipse plugin setup and working. I can open up eclipse and view the project fine. Where my questions/issues are coming from is trying to link existing source into the gradle setup. Previously, I have kept all of my source separate from the eclipse workspaces by importing the project as a separate project, and then linking source folders into the existing Minecraft project. All I had to do when it came time to recompile was copy the source into the actual mcp /src directory / recompile/reobfuscate (done through a batch file/build script). What is the best method to link source an existing source folder into the new setup? I have currently just linked my source folder into the gradle project. It seems to work so far (at least it is throwing all of the errors I would expect for a non-updated mod), but I can see that when I run 'gradlew build' it does not even attempt to recompile any of my source. Will I need to make another script/etc to copy my source into the /src folder for recompilation? Is there a cleaner way of setting this up? I'm guessing the preferred method is to code right into the /src directory of the project -- which I'm not quite sure how this would work out with many projects going on at the same time. I guess the end question is -- does the 'just copy into the /src folder for recompile and reobfuscate' trick still work, or am I going to need to completely re-arrange my work-layout? Also, slightly off-topic -- is there any support for multiple MC / forge versions with gradle? As near as I can tell it is limited to the currently 'setup' version, and only one MC version at a time. I ask because I often keep my mods updated for the last 2 major MC udpates (e.g. currently 1.5.2 and 1.6.4), and found the ability to keep an MCP setup around for each MC version quite handy.
×
×
  • Create New...

Important Information

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