shadowmage4513
Forge Modder-
Posts
157 -
Joined
-
Last visited
-
Days Won
1
Everything posted by shadowmage4513
-
You are hitting the client/server divide. What you are seeing is the correct values in the server copy of the block, but default values in the client-copy of the block. This is caused by not sending the info you want synched in the description packet. Look at the tile entity getDiscriptionPacket and onDataPacket methods, as they are the built-in server->client coms method for tile-entities. (basically, you tell the world server side to update the block on the clients)
-
It could also be that onItemRightClick is only firing server side, which of course is not going to open any GUIs. also, you are skipping the FML call, which handles the server-client comms packet to open the GUI client side if the call is made on the server. use if(!world.isremote) { FMLNetworkHandler.openGUI(params....<same as your openGUI call>) } in your onRightClick code. This will also require a properly setup IGuiHandler. Then, simply do the openGUI call on server side and it will both open the container server side (if used), and open the GUI client side. (Note, if you return NULL from the server getGuiElement method, it will NOT send the openGUI packet to client side, so these must be GuiContainer instances (even if just populated with an empty/dummy container)).
-
My method of storing persistent data for worlds, while not being a coremod, is to sideline a data file into the world-save folder, and to use onWorldSave and onWorldLoad events to trigger loading/saving of the data. I use basically an NBT tag to store it in, and CompressedStreamTools to write it into a file. A little code for a timestamp (don't want to re-load old data when a new dimension is loaded/reloaded) ,and clearing cache on logout, and you've got a persistent-data system running alongside MC that will load world-specific data. It is kind of ugly, and relies on that file not being separated from the world directory, but it has worked very well for me so far. Many other mods to the same (or very similar)--e.g. Greg-tech stores IDSU values in such a file, NEI stores world-inventory-saves into such a file--WRCBE stores world-specific frequency info in much the same manner. For examples of how these work, ChickenBones does release source for his mods, which should show you how/when to load the data.
-
Giving a Block dimensional features (like ender chest)?
shadowmage4513 replied to xKashanx's topic in Modder Support
If you think about it logically... Your block data will not exist in any _World_. It will only exist as _data_, stored somewhere in your mod. You will need a way to maintain this data across saves, and access it from any instance/copy of that block. So... you will need to sideline data alongside the world (i.e. store your data in a file in the world directory). This gets into the realm of writing custom .dat files, and using the onWorldLoad and onWorldSave events provided by Forge/FML. Several other mods already do very similar things. If you are looking for code examples--Look at the NEI code, ChickenBones stores the 'saved inventories' into a .dat file alongside the world (in the world folder). -
Wow...I'm going to quit trying to help people. I believe I correctly answered his question. Your answer was completely unhelpful, and so was your reply. This is why people never help/answer questions, I why I no longer will.
-
Client side health bars aren't 'impossible'. But, as stated, they require sending custom packets from server-> every client tracking that entity. (I believe there is even a function in one of the network handlers that does exactly that). I currently have client-side health bars for vehicles in my mod, using the above method. (send health in initial IEntityAdditionalSpawnData(sp?) packet, and then send updates to all tracking clients every time health changes.) Also there is a function IN the entities precisely for this use. I think it is called something like handleHealthUpdate(byte data), which is called in world.setEntityState(Entity ent , byte data) to send the packet to all players, without needing custom packets or handling. If you look in the wolf or golem code, you can see how this method is used to internally update client-side statistics (health determines a wolf's tail angle, and the golems use it to determine if they should display a rose or not).
-
[Solved] Limiting what goes in inventory slots
shadowmage4513 replied to defiant810's topic in Modder Support
The dupe item would be a client-side spawned item. Make sure in your code that spawns the entityItem, that it is only called server-side. For custom inventory validation--I used a custom slot and used the isItemValidForSlot method in the slot. However, I had to use some workarounds in order to get it to work while shift-clicking items. (normal transfer is easy with the slot method). Using this method, I am able to sucessfully tell a 12 slot inventory that it can only accept certain items in slots 0-5, different items in 6-8, and finally a different set it slots 9-11. I can provide links to source if needed. -
FML/forge mods do not edit base-classes. You are doing things wrong. Look into doing it as a coremod, using access transformers, reflection, and ASM. Edit--NEI is a great example of the correct way to do such a mod, as the previous poster suggested.
-
I believe itemStacks now have an NBT tag that can have custom information appended to it, which should be persistent across saves. However from what I read in the source, it is only applicable for non-stackable items (or is it that any item with a custom tag becomes non-stackable?) So, your answer may be in the ItemStack class, look up the custom NBT tag handling.
-
[Solved] Prevent entities de-spawning client-side
shadowmage4513 replied to Skerp's topic in Modder Support
try this: in the onUpdate for your entity, have it output the distance to the closest player if it is on server side if(!worldObj.isRemote) { //get closest player from world if(player!=null) { //output distance from this.getDistanceToEntity(player) } } if it stops outputting at a distance of 150'ish blocks, it is a chunkloading issue (meaning you will need to use Forge's forced-chunk loading system) if it continues outputting past 150'ish blocks, it is a render-distance or update distance issue. (also render distance is given as a sqRt, so in order to render out to 250 blocks, needs to be set as 250*250) Also, I dont' think chunks 'load client side' as you are thinking, or at least that has nothing to do with your entity being spawned/visible. Most of the entity stuff is handled server side (entity updates)--pretty much only positioning and rendering is done client side. So if the chunk is unloaded client-side, but still loaded server side, the entity will still update. If a chunk is somehow loaded on client but not on server, it doesn't matter because the server won't be doing any updating to that chunk. Anyhow..hope this helps..I know it took me a few days to sort over my chunkloading issues. -
I had this issue with a few items in my mod. The end solution? Use a PlayerTracker, and a HashMap or similar to store the player instances and their corresponding Hook instances. No need to edit base classes. You would just query PlayerTracker.instance().getHookForPlayer() or similar, and set through PlayerTracker.instance().setHookForPlayer(EntityHook ent) If persistence across saves is needed, you can save all of the data out to a custom NBT file. Offtimes modding in MC is a game of compromise because of base-classes and inabilty to alter them.
-
[Solved] Prevent entities de-spawning client-side
shadowmage4513 replied to Skerp's topic in Modder Support
You are probably hitting on about 3-4 different issues simultaneously here. One of them is render distance. This can be set in the entity, through an overrided method. A second is chunk-loading. You will need to setup chunkloading for your entity if you want it to stay loaded past about ~140 blocks range. The third is the update range--position/velocity update packets won't be sent to players beyond this range. So, in order to make an entity persistent (and visible) you will need to set your render distance in the entity, setup chunkloading for your mod and register the entity to a chunk-ticket, and set the updateRange where you registered your entity up to the range you want it to update. I had some missiles in my mod that I had to do this to, in order to make them continue flying at long range/explode on impact at any range > 140 blocks. Works great now though. -
Tile entity saving weirdly when world is reloaded.
shadowmage4513 replied to wog890's topic in Modder Support
you need to implement and override the extra client-side data methods such as: /** * whenever this TE is freshly sent to a client or marked for update in the world this entire packet will be sent to all tracking player */ @Override public Packet getDescriptionPacket() { NBTTagCompound tileTag = new NBTTagCompound(); this.writeToNBT(tileTag); return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 0, tileTag); } /** * Called when you receive a TileEntityData packet for the location this * TileEntity is currently in. On the client, the NetworkManager will always * be the remote server. On the server, it will be whomever is responsible for * sending the packet. * * @param net The NetworkManager the packet originated from * @param pkt The data packet */ @Override public void onDataPacket(INetworkManager net, Packet132TileEntityData pkt) { this.readFromNBT(pkt.customParam1); } Ohh..and gates...check out my mod at ancientwarfare.wikispaces.com -- I've had both wooden and iron drop-type gates for quite a while. (might be willing to point you towards some source if you'de like) -
The important part is : File part1 = MinecraftServer.getServer().getFile(""); String part2 = MinecraftServer.getServer().getFolderName(); String filePart2 = part1+"/saves/"+part2; if((MinecraftServer.getServer() instanceof DedicatedServer)) { //override the previous statement if it is run on dedicated server filePart2 = part1+"/"+part2; } Took me a bit to track it all down, but it correctly saves to world-save folder on both integrated and dedicated servers. public void onWorldLoad(WorldServer worldServer) { this.loadedWorlds++; /** * load stats file, populate globalTag */ File part1 = MinecraftServer.getServer().getFile(""); String part2 = MinecraftServer.getServer().getFolderName(); String filePart2 = part1+"/saves/"+part2; if((MinecraftServer.getServer() instanceof DedicatedServer)) { filePart2 = part1+"/"+part2; } if(!filePart2.equals(filePath)) { this.filePath = filePart2; this.resetAllTrackedData(); } File rawFile = new File(filePart2,"catModGlobalStats.dat"); NBTTagCompound tempTagData = null; try { tempTagData = CompressedStreamTools.read(rawFile); } catch (IOException e) { System.out.println("could not load globalStats, no such file, or improper format"); return; } if(tempTagData!=null) { if(this.isTagLoaded) { /** * compare timestamps...if the just read one is OLDER than the existing copy....do nothing */ long time = tempTagData.getLong("tS"); if(!this.compareDates(globalTag.getLong("tS"), time)) { return; } } globalTag = tempTagData; PlayerTracker.instance().loadFromNBT(this.getPlayerTrackingData()); CatapultMod.serverTeamTracker.loadFromNBT(this.getTeamData()); this.isTagLoaded = true; } } /** * compare two long dates as timestamps, returns true if the second is newer than the first, false if first * is newer * @return */ public boolean compareDates(long first, long second) { Timestamp t1 = new Timestamp(first); Timestamp t2 = new Timestamp(second); return t2.after(t1); } public String filePath = ""; public void onWorldSave(WorldServer worldServer) { /** * save system time into tag */ globalTag.setLong("tS", System.currentTimeMillis()); File part1 = MinecraftServer.getServer().getFile(""); String part2 = MinecraftServer.getServer().getFolderName(); String filePart2 = part1+"/saves/"+part2; if((MinecraftServer.getServer() instanceof DedicatedServer)) { filePart2 = part1+"/"+part2; } File rawFile = new File(filePart2,"catModGlobalStats.dat"); try { this.filePath = filePart2; this.updatePlayerTrackingData(PlayerTracker.instance().saveToNBT()); this.updateTeamData(CatapultMod.serverTeamTracker.getTagToSaveToNBT()); CompressedStreamTools.write(globalTag, rawFile); } catch (IOException e) { System.out.println("error writing stats to file, wtf"); return; } }
-
[Solved] Keeping TileEntity client-side in sync every second
shadowmage4513 replied to Narrakan's topic in Modder Support
I think the cleaner solution is to use the built-in tile-entity packet sending stuff---you were on the right track. The trick is, on server side when you need to send updates to clients, do world.markblocksasneedsupdate(x,y,z) <sp? don't have my source ATM>, and it will force-resend the TE NBT tag/packet, just as if it was first initialized/sent to the client. Run a counter in the TE entityUpdate method to mark as dirty every second (or just mark as dirty whenever you actually need to send the info). -
Is your MeteorHandler setup with the same information for both client and server side? Also, when creatures are spawned client side, they are spawned using the default one arg (World world) constructor. If you have additional data set by your server-side constructor, you need to pass that through the IEntityAdditionalSpawnData read and write streams interface so that the client receives the data after spawning the entity and applies it correctly (such as entity size, textures, entityType, all of the values you are putting in your constructor/setting up in your constructor).
-
Hi all, I have some custom coded entities with attack priorities based upon Entity class types. I have no problem getting my entities to target vanilla mobs, but would like to be able to include the option to add entity types from other mods. I realize this will have to be populated at run-time, after mods have loaded and initialized. I can see a way to get a list of installed mods (ModContainers), but cannot find an effective solution for getting a list of entities registered to that mod. The current best solution I can find would be to run a for/loop for every mod container, for every entity id between 0-255, poll EntityRegistry.lookupModSpawn(ModContainer mc, int modEntityId). This would result in a ton of iterating through null entries though/iterating through the same list many times. Thanks in advance for any help, much appreciated. Edit: As usual, I was going about the whole process wrong, and forgetting about vanilla MC interfaces. Sometimes I seem to enjoy doing things the hard way. It appears that the EntityList has everything that I will need to populate a list of entities in the game at run-time.
-
In order to get your custom render called, you must register it with RenderingRegistry. In your client proxy/client side onLoad code: RenderingRegistry.registerEntityRenderingHandler(render_name_here.class, new EntityToBeRendered());
-
Either a: use the onRandomTick (sp?) method in the block, take the passed in corrdinates, and pull an entity list from the world for an AABB near the block. or b: use a tile entity for the block, and do the same thing from an update tick from the tile entity. brief questions get brief answers.
-
Yes, pretty much as you are thinking. (and yes, the boat code is crap) I have done alot of vehicle type work for my mod (ancientwarfare.wikispaces.com) and my solution: Handle client movement on the client, relay information to the server regarding input. Do not let server update local (ridden) client, only let server relay motion and input to other clients. That way the player riding the entity gets 100% smooth motion, done client side. Server gets relayed position and input updates from client periodically, and relays these to other clients. Movement on other clients is sometimes jumpy......but it was either suffer from boat issues in first-person, or let the third-party see a bit of jumping (which actually is not too bad with this model). Basically--register a dummy keybind handler(see FML javadocs), tick handler on client to poll for keys pressed--actually I used a proxy class for the vehicleMovementHelper, and relayed from that--, and when input changes, relay the new change to the server (no need to relay every tick, only when changed). Server then relays to all _other_ clients the new input/velocity/position. Hopefully someone has a better model than this (as I'm looking to redo it), but it was the best solution I could find to solve the jumpiness client side. I've got my source up on github, and can provide links/examples if necessary (send me a PM, or w/e).
-
Ahh, that was info I've never seen. No, I've never tried to use ALL the bits of a blocks meta-data. Armed with that knowledge...it makes me wonder why they even leave an int open in the block for meta-data? Wouldn't it more clearly convey what it is for as a boolean bitfield...or something more representative of its true size? (smaller than short...bigger than byte...hmm) Thanks for the link, and sorry for posting _uninformed/incorrect_ information.
-
actually... metadata is an int which gives you 32(31) workable bits for metadata you can break those bits into smaller chunks so that bits 0-3 store rotation value, 4-x store operational state, x-xx stores timer values...etc. Requires knowledge of bitshifting and bitwise operators (bitwise and, bitwise or). Several vanilla blocks do exactly that for rotational metadata. The repeater, for instance. Stores its rotation, delay ticks, and on-state all in meta-data. Pistons do much the same thing. I have a crafting table block that stores its rotation and current operational state both in metadata (requires breaking it up into bits to decode though). Tile entities are certainly another option though, and can be much easier to work with than bitfields and bitwise operations.
-
Entity wont spawn when created in GUIScreen
shadowmage4513 replied to shucke's topic in Modder Support
No worries, I had kind of inferred you were trying to spit out items. basically, you need to construct a new ItemStack to feed the entityItem, which is as simple as EntityItem var12 = new EntityItem(par0World, par6, par8 - 0.3D, par10, new ItemStack(itemID, quantity)); replace itemID with the shiftedIndex for the item you are trying to spawn. replace quantity with the quantity you want dispensed. Hope that helps EDIT--Sorry, apparently I gave you the wrong constructor, and it should be new ItemStack(Item, quantity). There is a three int constructor (itemID, qty, dmg). You can get the item directly by calling the static Item that you declared / that is declared in minecraft i.e. Item.silk, or Your_Mod_Item_Loader._your_item_name -
Entity wont spawn when created in GUIScreen
shadowmage4513 replied to shucke's topic in Modder Support
Are you trying to spawn an entity, or do something with items? Item ID's have nothing to do with entities. If you are trying to give your player an item, that is something completely seperate, and should probably be handled in a container. If you are tyring to have your vending machine spit out an EntityItem, that again..is something seperate (kind of related). In that case, find the code that spawns entityItems, and give it your itemID that you want to have spawned. "but how can i see what itemid is belongs to what item?" ? You pull them from the item in-game. Something like Item.silk.shiftedIndex will get you the itemID of a particular item--use that itemID when spawning an EntityItem (look for the EntityItem spawning source code in the game source--it is there) -
How to make smooth moving \ player\items iteraction on block
shadowmage4513 replied to crashtua's topic in Modder Support
Without looking at the code, I would say he has implemented some custom entities that take on the shape of blocks. Blocks AFAIK cannot move--they are just information in an array. If it moves (smoothly), it is an entity. From there, custom collision handling, custom powered-block handling, custom rendering, custom interaction code...umm...yup, that sounds about right.