shadowmage4513
Forge Modder-
Posts
157 -
Joined
-
Last visited
-
Days Won
1
Everything posted by shadowmage4513
-
You may very well be correct about the per-frame costs. The renderWorldLast method doesn't have an easy way to setup/call an optimized displayList, so it has to rebuild/recalculate per-frame. I am by no means a rendering expert though, so others may have more accurate info/input on it. Please keep us informed if you do find a better process to accomplish your goal, would be interested in hearing about it
-
to answer your question -- yes you can. simply test if motionX, motionY, AND motionZ are all == 0. If 0, the entity is truly stopped. The long answer...they are adjustment vectors from the current position. So, if entity is at X = 1.42, and motion X = -0.12, then after the next update tick, the entities position would be X=1.30. If motionX was +0.12, the entity would be instead at X=1.54. testing for exact zero for 'stopped' can be misleading...some of those numbers can be very small but non-zero, and the entity would appear stopped for all intents and purposes. It might be better to test for sqrt(mx*mx+my*my+mz*mz)<=0.002 to see if the entity is just moving really really slow, and might as well be stopped
-
Perhaps a bit of a different method: There is a renderWorldLast event--called after other world rendering to allow you to render things in ...the world. You would need to synch a list of the 'highlighted' blocks between server + clients (packets, basic synch stuff), but then could simply use the renderWorldLast event to directly render your highlights -- no need for entities and the overhead they bring, or trying to use block renderers. Using the event, you could theoretically render...anything you wanted. It seems to work well with transparency and occlusion (I have it rendering large bounding boxes around block-selections as well, using semi-transparent lines). (see https://github.com/shadowmage45/AncientWarfare/blob/master/AncientWarfare/src/shadowmage/ancient_warfare/client/render/AWRenderHelper.java#L201 for examples)
-
here is the information that I found useful when I made my implementation of saving to world save folder.... http://www.minecraftforge.net/forum/index.php?topic=8520.0 https://github.com/diesieben07/Questology/blob/e9f46d8b3aa41b82f9021c892bca7ee558e7899a/source/demonmodders/questology/QuestologyWorldData.java and... my implementation..with load/save stuff https://github.com/shadowmage45/AncientWarfare/tree/master/AncientWarfare/src/shadowmage/ancient_warfare/common/tracker (hint...load/save are handled mostly automatically whenever the world loads/saves, you just need to make sure you keep the data up-to-date) Oh hey...Hi diesieben07 hope you don't mind I used your previous example(s)
-
How to add a renderer on top of an existing minecraft gui
shadowmage4513 replied to tlr38usd's topic in Modder Support
you can still use the methods from your gui-extending class even when MC isn't 'displaying' that GUI -- this is how I render health bars for my vehicles in an overlay. in your client tick handler, have a reference to your gui-extending object, and onTick() just call the render methods for (from/within) your GUI. -
Hi all, Wondering what the best known method for a soft-mod dependency is? My current method is this: Use reflection to check if the class-name for the mod in question exists (called during pre-init, so info can be used for block setup). Load a different plugin proxy class based on whether the mod exists or not. Plugin Proxy contains any methods differentiated when the 'soft dependency' is installed. Any block/item loaders will call to the proxy to get the block/item classes (and instances) for the blocks/items that are different when the soft dependency is installed. (E.g. the plugin proxy can return a BC based Tile Entity when it detects BC installed, or return a vanilla TE if no BC detected). The method seems to work fine even after repackaging distributing. It loads the BC stuff with BC installed, loads the normal stuff without BC installed, and doesn't crash. Basically, it works, but it feels very hacky (reflection...ughh..). Is there a proper way to do this through Forge/FML hooks that I haven't noticed ? (seems like a getting a list of installed/loaded mods would work, but only after init phases are done loading them, thus precluding differentiation of blocks/items based on installed mod status)
-
Mod wont work after recompiling and Reobfuocate_Srg
shadowmage4513 replied to poonkje112's topic in Modder Support
your @Instance() line should actually have the name of the modID, not the name of the class so it should be (from your example) @Instance("OpticalItems") public static MainClass instance; otherwise, what happens is FML tries to find a mod named "MainClass" to inject the main mod file into the instance field of your MainClass (which it won't find, and hence the crash). -
Mod not working on server... Creative tabs issue
shadowmage4513 replied to Yagoki's topic in Modder Support
The most common cause of that issue would be id mismatch between client/server, or the mod not being present on the server. the source points to ItemStack.java: public int getItemDamage() { return this.getItem().getItemDamageFromStack(this); } as being the cause of the issue. (likely caused by a null Item reference in the ItemStack) In a few recent Forge releases there were some issues with calling getItemDamage() causing NPE when called with certain items (i don't remember the exact circumstances though...) -- so if neither of the first problems is your issue, you might try updating the Forge/FML on both your client(s) and server. -
If you are referring to intercepting vanilla packets to handle them yourself -- I don't believe this functionality is currently included in Forge (there was a PR/talk about it a few weeks/month ago, but I haven't seen it in the repo yet). If you are referring to sending/receiving those packets yourself (to/from your mod)-- again, not really possible (you can send the packets, but vanilla packet handler will pick them up). However, you should be able to use the Packet250 to hold any of the datas sent through the other packets, you would just need to make your own subclass of Packet250, override the necessary read/write methods, and of course handle it in your own packet handler.
-
Any way to check if the player is spawned?
shadowmage4513 replied to freeradicalx's topic in Modder Support
Use Forge's LivingSpawnEvent, then checkcast the EntityLiving obj to EntityPlayer. What he said ^^ Also, try and avoid using Minecraft.getMinecraft() any any SMP mod, as it is a client-side only method and will not run properly if compiled/placed on dedicated server. (unecessary for SSP only mods, but probably a good idea to do things properly from the get-go) There is also a way to get a list of all logged in player entities from MinecraftServer.... I think it is located at: MinecraftServer.getServer().getConfigurationManager().playerEntityList Which would allow for active/realtime polling of player positions/knowing when they are online. (And this method is SMP safe, and could safely be called on a dedicated server). -
Opening GUI on player's client from server
shadowmage4513 replied to twixthehero's topic in Modder Support
IF you want to open a client-side gui from a server side action you need one of two things. A: A Container server side. It can be a dummy container with no slots. (this is my personal route), or B: You will need to manually send a packet to the particular client, and in your packet handling call open GUI. Option B is pretty much re-creating the wheel, but the only way to do it if you absolutely do not want a container. Option A is pretty straightforward --make a container class with no slots, and empty methods-- just make sure to call player.closeGUI() when closing so that the containers stay in sync client/server sides. Return this 'dummy' container from the server-side getGuiElement call -- and THEN FML will send the packet to client-side to open the GUI. (it won't send the packet to client if there is no container returned--it assumes all client-side only guis are handled..client-side only). -
[UNSOLVED] Making the player move forward?
shadowmage4513 replied to ryanhami's topic in Modder Support
Not sure how it will play with client/server stuff, but you can just call player.moveEntity(xVec, yVec, zVec) (server side) with the motion that you want to move that tick (so, will need a tick handler to do the movement on every tick that is needed and other methods to know when you need to do the moving). (the moveEntity method is what gets called to do the actual movement from the players internal motionX/Y/Z variables during the entity update) As I said, not sure how it will work on players, especially the SP/client player, but it _should_ even work in that case. -
I used the RenderWorldLast event for my world-rendering hooks. It allows me to draw bounding boxes in the world regardless of player position, and without needing blocks/etc. It should be fairly simple to hook in to draw a nameplate/etc above the players head (would just need the proper transformation set up).
-
How to add liquid tanks to your container?
shadowmage4513 replied to larsgerrits's topic in Modder Support
Probably the best place to start is the Buildcraft repo on Github -- it should have all the source that you need to see exactly how they did it. (sorry, I don't actually know myself, and will be going this same route before too long -- e.g. looking in BC source) -
Set the entity size in the entity constructor. It is likely the default height (1.8 blocks I think) try setSize(1.0f, 1.0f); should set both the width and height to 1 block (method is called with width first, then height) The y position bit is likely related to the yOffset I believe (Not really sure, I set the yOffset on all of my entities to 0).
-
Ray tracing from an entity's head angle.
shadowmage4513 replied to BlueSpud's topic in Modder Support
Yes, the tracePath function takes essentially two vectors x,y,z for start vector, and tx,ty,tz for target vector (end of the ray). Border size merely expands the search radius slightly beyond what it would normally get (not sure if it actually needed, it was intended to grab entities that were technically outside of the bounding box but could still be collided -- I use it with a value of 0.2f). -
Ray tracing from an entity's head angle.
shadowmage4513 replied to BlueSpud's topic in Modder Support
if you are referring to testing if the target hit is a player: the method returns a movingObjectPosition object, which has an internal field for an entity hit if any-- will be null if no entity was hit. (it may also return null entirely, meaning no object was hit during the trace) MovingObjectPosition hit = tracePath(world, x,y,z, x1, y1,z1); if(hit!=null && hit.entityHit instanceof EntityPlayer) { //do logic } the instanceof operator essentially entails a null check and run-time class check (usually the only way to tell entity classes/subclasses apart) -
Ray tracing from an entity's head angle.
shadowmage4513 replied to BlueSpud's topic in Modder Support
MC has _built_in_ methods for doing ray-casting/raytracing. (although it is kind of sloppy, you have to trace once for blocks, and again for entities). For blocks, the method is located in world. Entitiy collision detection is a bit more complex. Perhaps a code example would work best --taken from a utility class (hence the static method) simply call it with with the position of the head of the entity, and the target end-vector. The end-vector can be calculated with some 'simple' trig (take the yaw/pitch of the head, determine what distance you want to check out to, and apply some translation to get an endpoint/target point). public static MovingObjectPosition tracePath(World world, float x, float y, float z, float tx, float ty, float tz, float borderSize, HashSet<Entity> excluded) { Vec3 startVec = Vec3.fakePool.getVecFromPool(x, y, z); Vec3 lookVec = Vec3.fakePool.getVecFromPool(tx-x, ty-y, tz-z); Vec3 endVec = Vec3.fakePool.getVecFromPool(tx, ty, tz); float minX = x < tx ? x : tx; float minY = y < ty ? y : ty; float minZ = z < tz ? z : tz; float maxX = x > tx ? x : tx; float maxY = y > ty ? y : ty; float maxZ = z > tz ? z : tz; AxisAlignedBB bb = AxisAlignedBB.getAABBPool().getAABB(minX, minY, minZ, maxX, maxY, maxZ).expand(borderSize, borderSize, borderSize); List<Entity> allEntities = world.getEntitiesWithinAABBExcludingEntity(null, bb); MovingObjectPosition blockHit = world.rayTraceBlocks(startVec, endVec); startVec = Vec3.fakePool.getVecFromPool(x, y, z); endVec = Vec3.fakePool.getVecFromPool(tx, ty, tz); float maxDistance = (float) endVec.distanceTo(startVec); if(blockHit!=null) { maxDistance = (float) blockHit.hitVec.distanceTo(startVec); } Entity closestHitEntity = null; float closestHit = Float.POSITIVE_INFINITY; float currentHit = 0.f; AxisAlignedBB entityBb;// = ent.getBoundingBox(); MovingObjectPosition intercept; for(Entity ent : allEntities) { if(ent.canBeCollidedWith() && !excluded.contains(ent)) { float entBorder = ent.getCollisionBorderSize(); entityBb = ent.boundingBox; if(entityBb!=null) { entityBb = entityBb.expand(entBorder, entBorder, entBorder); intercept = entityBb.calculateIntercept(startVec, endVec); if(intercept!=null) { currentHit = (float) intercept.hitVec.distanceTo(startVec); if(currentHit < closestHit || currentHit==0) { closestHit = currentHit; closestHitEntity = ent; } } } } } if(closestHitEntity!=null) { blockHit = new MovingObjectPosition(closestHitEntity); } return blockHit; } This code is _heavily_ based upon the code found in entityPlayer that determines the block/entity to hit/interact with. It first ray-traces for a block hit (using the world raytrace methods), and sets that as the real end-point of the ray-trace. It then grabs all entities in the remaining bounding box, and tests each of those for collision. -
Thanks SanAndreasP, I think the move-speed thing can be solved 'fairly' easily (more reflection to pull the default moveSpeed out of the mob). Your solution might be the way to go. Trying to insert AI tasks will be problematic with some mobs, but it looks like most mobs use the revenge-target/attack target methods to at least some effect. I was really hoping to find a method to set during mob spawning/creation, and not have to have my npcs 'broadcast' for aggro at all, but its looking like it won't really be feasible with the current state of things. One final question -- I've mostly stayed away from reflection for various reasons (specifically reflecting on obfuscated code) -- I see that you are pulling the private field by field name -- If I go this route, all I should really have to worry about is renaming the field in my code if the name changes in an MC update ? (e.g. how stable is it generally between forge/MCP versions for the same MC version?)
-
Thanks for the reply, Yes, I'm looking for a method to set vanilla entities to be hostile towards mine. I'm thinking I could probably use the two methods I pointed out above, but they would be specialized per-vanilla mob, and not really what I'm looking for (e.g. I would have to set zombie AI one way, skeleton another, witches yet another, etc...). I was hoping someone had come across and solved this one before (or at least that I had missed something obvious in the MC source). Off topic: The NPCs are more like assorted RTS units -- peons/workers, melee units, archers, siege-engine drivers. Not custom-scriptable or storyline oriented -- more production/resource/combat oriented.
-
Hi all, I was wondering if anyone is aware of a method for setting vanilla entities to be aggro vs. another entity? For example my mod introduces new NPCs. I would like zombies/skeletons/etc to attack these entities as they would a player. I've tried a couple solutions with out (much) luck. First -- Using entity join world event to add targeting tasks (more for the zombie than others) -- I can get the zombie to 'look at' my NPCs, but their speed is not being set properly for the task (and moveSpeed field is protected/not accessible from the event). I could manually set the speed for the mob, but would still need to be able to access the moveSpeed field. (or manually map class -> speed for a lookup table) Also, this method will only work for 'new AI enabled' mobs as far as I can tell (zombie, skeleton). //@ForgeSubscribe //public void onEntitySpawn(EntityJoinWorldEvent evt) // { // if(evt.entity instanceof EntityMob) // { // EntityMob zomb = (EntityMob)evt.entity; // Config.logDebug("setting entity attack tasks for: "+zomb); // zomb.tasks.addTask(3, new EntityAIAttackOnCollide(zomb, NpcBase.class, zomb.getAIMoveSpeed(), true)); //<--yes I know getAIMoveSpeed() is incorrect...... // zomb.targetTasks.addTask(2, new EntityAINearestAttackableTarget(zomb, NpcBase.class, 16.0F, 0, true)); // } // } Second-- Tried having my NPCs 'broadcast' attack/revenge targets to nearby EntityMob entities. Works good for skeletons, but not on zombie pig-men (didn't really check past that). protected void broadcastAggro() { List<EntityMob> mobs = worldObj.getEntitiesWithinAABB(EntityMob.class, AxisAlignedBB.getAABBPool().getAABB(posX-16, posY-8, posZ-16, posX+16, posY+8, posZ+16)); for(EntityMob mob : mobs) { if(mob.getAttackTarget()==null) { Config.logDebug("setting mob attack target"); mob.setRevengeTarget(this); } } } So, I've got a couple of 'hacks' that 'work' for specific mobs, but are not something I really want to implement, and I'm really looking for something a bit more abstract that will work for _all_ vanilla mobs (and hopefully at least some mod-entities/mobs). Is anyone aware of a 'proper' method to handle this? Thanks in advance,
-
[SOLVED][1.4.7]Ore Generating Above Ground
shadowmage4513 replied to Vemahk20's topic in Modder Support
Quite simply, you are not checking to see if it is a valid gen-replaceable block before generating your ores. You need to check if the block going to be replaced is world-gen replaceable / stone int x = chunkX*16 +random.nextInt(16); int y = chunkY*16 +random.nextInt(16); int z = chunkZ*16 +random.nextInt(16); int id = world.getBlockID(x,y,z); Block block = Block.blocksList[id]; if(block!=null && block.isGenMineableReplaceable(world, x, y, z, Block.stone.blockID)) { //set your blocks here.... } -
Entities don't have 'sides' like blocks do. What you could do however, is check the yaw bearing from the player to the target (or vice-versa) yaw to the target that would have been hit. You can also do this on the y axis to get the pitch to the target. This can be done using Math.atan2(z,x) to find the yaw, translating x and z to a length and then doing the same for those (Math.atan2(len,y) (might be (y, len))... From the yaw and pitch you can determine what 'side' was hit. if yaw from player to target is between 315 <-> 45, you hit the south side, if it is between 45 <-> 135, you hit the east side. 135 <-> 225 north side hit, 225 <-> 315 is west side hit. That gives you a general 'side hit', although it doesn't take care of checking actual hits vs. a bounding box. For that you would likely need to implement some simple ray-tracing through voxels using an offset from world coordinates (see Bresenham's Algorithm for a start) to see what side you actual impacted on.