-
Posts
2638 -
Joined
-
Last visited
-
Days Won
4
Everything posted by Ernio
-
Particles are client side. Show you spawning code.
-
[1.8] prevent item switch animation upon nbt change
Ernio replied to sigurd4's topic in Modder Support
http://www.minecraftforge.net/forum/index.php/topic,30937.msg160967.html#msg160967 Issue has been tackled countless times (I've personally seen it at least 10 times in past months). Currently there is no hook to cancel that "action". Most of coders end up doing tricks (see linked thread). There will probably be PR for this very soon as i noticed - "heavy" modders started running into this issue (I personally will be using it in near future). -
I wouldn't use "#set(...) but whatever (use #clear() and then #add(...)) (not necessarily) As to problem - you are now only comparing Block - you also need to check if the meta of blockState is stone - meta=0; Then indeed add new ItemStack, with one change: Item.getItemFromBlock(the block you want) + the meta (like you did).
-
I am not a professional coder, never studied it (just learned), it's more of a hobby. Question is: In order to make namings "nice" - is it worth to make static classes, e.g: public class ItemCore extends Item { public ItemCore(String name) { super(); //whatever (cut) } public static class ItemDust extends ItemCore { public ItemDust(String name); { super("dust_" + name); } } public static class ItemOil extends ItemCore { public ItemOil(String name) { super("oil_" + name); } } } Meaning - is there a VALID (good practice or bad?) point in making it, or is it pointless?
-
Lag lag lag lag lag, lag, lag lag lag. Lag. Lol, I died. http://d24w6bsrhbeh9d.cloudfront.net/photo/adNbrdZ_460sa.gif[/img]
-
Bro/Gurl - learn about bitwise operations. I don't know what vanilla does and I don't care, but yes - it is possible to ship lots of info in just one DataWatcher value. e.g. byte has 8 bits. Each of those can be used as boolean, or combination of booleans. You can even send long in which you can store int, or few shorts and booleans - whatever.
-
In what scale? If you plan on having tons of given TE - then yes, markDirty used on every tick will cause extensive CPU usage - by extensive i don't mean it will be hell, but surely it will be much more than it should be. MD should be only called when needed. Check out Furnace - it has nice way of doing it (state-change booelan "isBurning()"). Btw. "Lag" is more of network problem. What you are asking is more of CPU usage.
-
[1.7.10-SOLVED] How to make a "movable" shaped recipe?
Ernio replied to TheDoctorSoda's topic in Modder Support
It's automated (I mean I think so). You don't have to do anything. Simply make: XXX XXX Recipe should work for any place. -
Thats wasn't it, tho it might cause miscalculations in future, thx. As to problem - it indeed turned out to be vanillas behaviour. Something I asked about few days ago - "shouldRefresh" method. It is defaulted to true for non-vanilla TEs. This caused my client-side container to have "old" TE reference in it, while the world's TE in BlockPos I was currently operating on got new TE when its blockState changed from normal to active block. While I was tracking and printing out everything inside, the error was actually totally outside and I realized it when started printing object's hex int of "this" (the TileEntity itself). Remember kids: When blockState changes - while the server's TE is kept intact - the client one will, by default, change to new TE - thus creating outdated object references. Fix: Made #shouldRefresh(...) return false there is relation between blocks' blockStates "normal" and "active". Note for others: NEVER return "false" in all cases - it will cause client's world to not remove TE in given place, even when server removes it. While it is NOT unsafe (something like ghost block) and will not cause errors (TE will get removed on world-reload), it might cause unwanted client actions (e.g particle spawning). SOLVED. In your face vanilla! #hate EDIT Btw, there is typo in forge public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) //newSate
-
Irrelevant code has been removed. Container: http://pastebin.com/MhsgwVP7 TileEntity: http://pastebin.com/9NEkGvR9 Those are abstracts, if you'd have to actually understand what's going on in implementation - took me more than week to just design it, waste of time looking there. I am SURE that there is no error in removed code (checked word by word, call by call). TheKey is a simple Enum containing "TIN". EDIT Note: If the value reaches 0.0D or null the Entry is deleted. Double "value" can never be null during map iteration. @Diesieben, will this suffice or you wanted whole mod implementation to test it? The mistake is most certainly not in anything I wrote. There is no "REAL" error here - the values exist, it's just (as described before) that they are (changes) ignored by onUpdate().
-
[1.8] Metadata limited to 4 bits - possible alternatives
Ernio replied to Reygok's topic in Modder Support
How common is your block? How many .png combinations there are? (simplier, how mny .png you want to use for single block)? -
http://img-9gag-lol.9cache.com/photo/aPy7mwn_460sa_v1.gif[/img] I strongly belive that this has something to do with threads, because at my level of understanding java internals - it's impossible for single object to give different values for two different callers. I don't think this is how it is supposed to work. Just after setting it to 100.0, the #update(): @Override public void update() { System.out.println("Something: TIN: " + this.map.get(KeyX.TIN)); Will never return just-changed values. It's like the map is not synchronized with the object that was changed. Funny enough that I actually did outside check and this exact object accessed on CLIENT from outside update() actually HAS new-changed value. (it's like #update() doesn't care about changes and prints out old stuff (not updated map object), even if I am directly referencing it). I am done... Once again, my arch nemesis - Vanilla - You did your best to make me waste another hours of life. (read signature, everything has reasons) One last thing - how is this possible for same-damn object (belive me when I say "same") to return different value for different callers? I've neve been to synchronized Java, and if I am guessing right - Vanilla does't do well with it.
-
Oh, so just want to grab moment when client's rendering it? There is RenderGameOverlayEvent. It has render phases. Looking at it now I can't see which one is title phase (might not exist, or I am outdated). I'd try TEXT, or ALL. EDIT If there is no EXACT event to cancel and render your own stuff - you will have to handle it on your own. Simply check if there is title to display on client, and if so - call your rendering. Might be tricky.
-
Have look at this: https://github.com/Questology/Questology/blob/master/src/main/java/demonmodders/questology/QuestologyWorldData.java Something that I personally never used, but read/heard that some find solutions there (it looks good to me).
-
This is in TE: public double getTotalAmount() { double total = 0.0; for (Double amount : this.map.values()) { total += amount; // note: value will never be null } return total; } And yes, map is in both container and TE. TE changes map, container will detect if last size is != current size, and then will scan it for changes that will be sent (double will be trimmed to int). I can go even without those current/last size (that was a simple cut of operations to about 25% when there are no changes), still that doesn't change anything. Problem lies exactly here: [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:setField:464]: SETTING KEY // as you can see - it's received [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:setField:472]: NEW KEY VALUE: TIN ; 100.0 // and when I get it from client's TileEntity - IT'S CORRECT! [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:setField:474]: 100.0 // size of map is 1 //Server's value is updated. [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: 100.0 // AND BAM - client's not - this is literally same/next tick Client received update few lines above. [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null // size of same map is 0 The key is being set, the EnumMap object is not changed (same one). When I get the value of key after setting it's 100.0, but just tiny bit after (first tick possible) it's again null - in same damn map. How is that possilbe? EDIT I realized why you wrote "keep a clone (!)" - and indeed, those two maps are "same" in manners they are initialized in same way, they are not exactly pointing to one object. So no issue here.
-
Alert: Mucho reading. I wouldn't come here if I hadn't debugged it for more than hour. I MUST be missing something. Situation: There is TileEntity that holds EnumMap<KeyX, Double> and container that holds SAME map. When TEs map change, container checks it and sends update to watchers (crafters). This map is sent to client's TE ONLY when someone is looking at container (using #sendProgressBarUpdate). Inside container's #detectAndSendChanges() private double lastMapAmount = 0.0D; // in container double currentMapAmout = this.tileEntity.getTotalAmount(); if (this.lastMapAmount != currentMapAmout) { System.out.println("LAST: " + this.lastMapAmount); System.out.println("CUR: " + currentMapAmout); for (KeyX key : KeyX.values()) { System.out.println(key); Double currentValue = this.tileEntity.getMap().get(key); System.out.println("CURRENT SERVER: " + currentValue); Double lastValue = this.map.get(key); System.out.println("LAST SERVER: " + lastValue); if (currentValue != lastValue) { System.out.println("NOT EXACT"); if (currentValue == null || currentValue == 0.0D) { System.out.println("NULL OR ZERO"); this.map.remove(key); } else { System.out.println("CHANGED"); this.map.put(key, currentValue); } sendToCrafters(material.ordinal()); // sends changes } } this.lastMapAmount = currentMapAmout; } private void sendToCrafters(int id) { for (int i = 0; i < this.crafters.size(); ++i) { ICrafting iCrafting = (ICrafting) this.crafters.get(i); iCrafting.sendProgressBarUpdate(this, id, this.tileEntity.getField(id)); //actually sends changes } } Receiver (container): @SideOnly(Side.CLIENT) public void updateProgressBar(int id, int data) { this.tileEntity.setField(id, data); } And in tileEntity: @Override public void setField(int id, int value) { System.out.println("SETTING KEY"); if (value <= 0) { System.out.println("REMOVEING CLIENT KEY"); this.map.remove(KeyX.values()[id]); } else { System.out.println("NEW KEY VALUE: " + KeyX.values()[id] + " ; " + Double.valueOf(value)); this.map.put(KeyX.values()[id], new Double(value)); System.out.println(this.map.get(KeyX.values()[id])); } } At start of update(), (in tileEntity) there is: @Override public void update() { System.out.println("Something: TIN: " + this.map.get(KeyX.TIN)); And console print: (// my actions) // I am looking at container //Here here we can see prints from update() // TIN is my only key in map. [12:19:46] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null //This is the #detectAndSendChanges() part, last is not equal to current (something changed) thus, sending new values to me, looking at container. [12:19:47] [server thread/INFO] [sTDOUT]: [something.ContainerSomething:detectAndSendChanges:101]: LAST: 0.0 [12:19:47] [server thread/INFO] [sTDOUT]: [something.ContainerSomething:detectAndSendChanges:102]: CUR: 100.0 // first and only Enum [12:19:47] [server thread/INFO] [sTDOUT]: [something.ContainerSomething:detectAndSendChanges:105]: TIN // the new value read from TileEntity [12:19:47] [server thread/INFO] [sTDOUT]: [something.ContainerSomething:detectAndSendChanges:107]: CURRENT SERVER: 100.0 // old value that was saved in container [12:19:47] [server thread/INFO] [sTDOUT]: [something.ContainerSomething:detectAndSendChanges:109]: LAST SERVER: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.ContainerSomething:detectAndSendChanges:112]: NOT EXACT [12:19:47] [server thread/INFO] [sTDOUT]: [something.ContainerSomething:detectAndSendChanges:120]: CHANGED // packet is being sent (update progress bar) [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:setField:464]: SETTING KEY // as you can see - it's received [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:setField:472]: NEW KEY VALUE: TIN ; 100.0 // and when I get it from client's TileEntity - IT'S CORRECT! [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:setField:474]: 100.0 //Server's value is updated. [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: 100.0 // AND BAM - client's not - this is literally same/next tick Client received update few lines above. [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: 100.0 [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: 100.0 [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: 100.0 [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null [12:19:47] [server thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: 100.0 [12:19:47] [Client thread/INFO] [sTDOUT]: [something.TileEntitySomething:update:78]: Something: TIN: null My questio nis WTF? I made sure that map is NOT accessed ANYWHERE else! What don't I know? Thanks. EDIT: I know that double is lost after packet, i am trimming double to int for client, they don't need it, only server has full value. EDIT 2: And yes, those are same objects, checked with System.identityHashCode(this.map)
-
Block doesn't have NBT, unless it's TileEntity. As to "boolean" - you can use metadata, but be warned that it is used by minecraft internals and won't work for vanilla - for your own block - sure, because you will read meta, for vanilla it's alredy used to define blocks.
-
Dude, what IDE are you using? There is no "looking" and "finding" here. You jsut click "Type Hierarchy" and you got them all listed.
-
Read again. --------- There is no "easy" way to do this. You either need to create placing storage or block replacements. 1. Storage: Create smart BlockPos storage that when performing event you want (e.g BreakEvent) will be checked if given block's position is in storage (placed by player). Now problem is - it will be tricky to track every change and may provide false data as some point (you know - you need to track every damn change). It's also not very efficient, best way would be to hash BlockPos and put it in hashMap for fast access. Only way I see it and has to be done smart. To save your "storage" you would need to implement WorldSaveData. 2. Block Replacement: For every block you want to track you need to create replacement copy. Since not-placed-by-player are placed by world you can hook into events that generate world and instead of placing vanilla ones, place yours. YourStone = created by world (replaced via generation event) Stone (vanilla) = placed by player, acts as normal stone. Now you know that Stone was placed, and only stone that was NOT placed it the one you made world generate instead of normal one. Both ways require some work and are not always "cool".
-
1. ALWAYS post your code. 2. ALWAYS define exact problem and situation, not "are acting weird". 3. ITS GOOD TO write what you are after (exactly, not "if it's possible", but "what i want") (Trying to help in future ) As to problem - world calls NBT-saving automatically. Anything that has to be saved in TE, will be savedloaded if you put it in write/read NBT methods. As to why it's not saving? - When you want TileEntity to save, you need to mark it as "dirty" to inform world that chunk TE is in needs to be saved to disk. this.markDirty() in TE.class
-
"I know how to write, that doesn't mean I write smart stuff." Not to be mean (I am kind person) but i have no idea what: ...has anything to do with IDE and "Type Hierarchy" in means of what I was talking about. There are 4 implementations of IChatComponent. Their names are pretty much self-exp and allow different formatting.
-
Then learn to use your IDE Ever heard about Type Hierarchy? (Tip: learn more java). Besides, I literally told you exact class name.
-
There is simply no such thing. Titles and scoreboards are handled internally by vanilla iteself. Why would forge rewrite it? You simply call vanilla methods like vanilla does it itself. Look at how vanilla does it and just create something that would be made by e.g command block, but instead of in command block - in code itself. Opinion: Vanilla features are sure nice and can be used while client doesn't have mod installed (server-side mod), but unless you plan to do that (write server mod) consider more options - I mean, modding allows you to make anything (why stay in simple things), that's the whole point and fun of it!
-
Read above. But if you need it - there is a list, idk if it's updated to latest version, but it has most (maybe all) of them. https://dl.dropboxusercontent.com/s/h777x7ugherqs0w/forgeevents.html
-
Dude, learn java a LITTLE better. Simply put IChatComponent as argument. There are several different components, for simplt text you have ChatComponentText (yes, declare new).