Jump to content

jabelar

Members
  • Posts

    3266
  • Joined

  • Last visited

  • Days Won

    39

Everything posted by jabelar

  1. Not sure exactly but see a couple things that might be related. I don't think you should be calling setDamage() in your performHurtAnimation() code. What is the purpose of that? In other classes that extend Entity, the attackEntityFrom() method returns false if on the client. I think your return value isn't quite right. It is meant to represent whether the entity took any damage. So instead of return this.isDead you should return true. Lastly, in your writeEntityToNBT() and readEntityToNBT() you need to store the values of your data parameters, otherwise the direction and damage will not save and load. Not sure if any of those things will fix your problem, but I think they are all things that should be fixed.
  2. You're using the spawn event improperly. Many events are "parent" events that actually fire multiple times for more specific subevents. In this case, the actual events are AllowDespawn, CheckSpawn, and CheckSpecialSpawn. So for example, the AllowDespawn is being regularly fired for all squids as they age in the world. I think you should use the CheckSpawn or perhaps the EntityJoinWorld events.
  3. You shouldn't have to handle the event for your own custom mob. Events are mostly for changing behavior of vanilla mobs. Your error is that the resource location is still not pointing to the proper file. I think that is because I don't think you need the loot_table/ in your resource location -- it already knows to look there. Instead maybe you should have: public static final ResourceLocation deathLootTable = new ResourceLocation(TheWizardMod.MODID, "entities/weird_zombie");
  4. Also, although it is good to think about performance the reality is that modern computers are getting faster and faster and a performance problem is only going to arise if you have a lot of something (or if you have big, recursive loops in your code, like scanning over lots of locations for something). In programming it is usually recommended to do things the "proper" way first -- meaning the typical, expected and readable way -- since that usually avoids introducing new bugs and makes it more easy to maintain. Then you should profile your code and see if there are any areas of undue performance burden and the rewrite those if needed. In other words, beds, chests, signs and other common minecraft stuff already use TESRs, so unless you expect to have a lot of your structures in the game then it shouldn't be much worse. Lastly, I hope that each version of minecraft gets performance improvements. I know sometimes they go backwards -- I remember that 1.8 had a bunch of lag issues -- but generally would expect it to get better. For example, maybe TESRs are more efficient in 1.12.1. Only way to know is to profile. Yes it is good to consider performance, but if you're going to go to coremods without even knowing how bad the performance is I suggest that you do more testing first.
  5. Ahh, good to know. Thanks.
  6. Okay, true I'm not familiar with what you're talking about but I've created pretty complicated dynamic lighting mods, for example see my moving light sources mod and my proposed method will work for what he's doing. http://jabelarminecraftmods.blogspot.com/p/jabelars-moving-light-source-mod.html
  7. Actually, you might be able to get away with just three tile entity blocks. One for the constant light, one for flicker off and one for flicker on. If you have randomness for the flicker off, you can give it a random chance of the flicker ending as well so each lamp will flicker a random number of times and eventually not replace itself and it will just remain as the off block. So, idea is: 1. place the constant on TE, it counts down until it should start to flicker. 2. it replaces itself with the flicker off TE, that creates a random counter and possibly ends the flickering. If flicker should continue and it counts down, it goes to next step. 3. It replaces itself with the flicker on TE, that creates a random counter, and when it counts down goes back to step 2.
  8. Does that allow the ignore frustum? I suggested an actual entity because I have experience knowing that ignoring frustum works for that.
  9. The night vision effect might work except it is from the perspective of the player, and so I don't think it would be easy to handle cases of multiple lamp blocks each timing out at different times. Instead I think you have to change the light value of individual lamp blocks. However, you can't just change the light value for your lamp block since that would change it for all lamps in the world at the same time. I think what you need to do is use a tile entity system where one is attached to a block with full light value and other with no light value (or low light value depending on the flicker effect you want). You would need two blocks with tile entities really, and each one would have to replace the other while passing information about the timer between them at the time of creation. You would need two timer fields in the light block TE, one for the constant light countdown and another for the flickering. In the non-light block TE you could just have the flickering timer. The light block TE would count down with constant light until it hits zero then would tick the flicker counter for a couple ticks (how ever long a flicker should be), then replace itself with the non-light block TE and pass the flicker counter to it, and the non-light block TE would count down a couple ticks and replace itself with a light block TE. Actually, since the passing of the information back and forth might be a bit tricky, it might be actually easier to create a number of blocks with TE each meant for next step of the flicker. So the main TE will replace itself with TE "flicker 0", which counts down and replaces itself with TE "flicker 1", etc. for as long as you want the flicker to last. You can make the count downs a bit random too for nicer flicker effect.
  10. You need to read a bit more about sides: http://mcforge.readthedocs.io/en/latest/concepts/sides/ Basically there is some code that runs on both sides, and in that case you can use the code you just mentioned. But there is other code that isn't even loaded on a side, so the Java virtual machine will crash if it tries to interpret it. Note that just having a reference to that code in your code can crash even if that code won't ever run on that side. Modders get fooled though because when running in single player mode both sides load in a single JVM. So the JVM can actually see the code loaded on the other side. But later if you run it on a dedicated server it will crash. I highly recommend that you test all your mods with a server run configuration in Eclipse to find these errors. Using the client run configuration only will hide them. I also have some explanation of sided code (and the use of proxies to manage some of it) here: http://mcforge.readthedocs.io/en/latest/concepts/sides/
  11. What they mean is that the function isn't really on a loop, rather it is being called on both the client and the server and for each of those called passing in ItemStack in each of the two hands. So you don't stop it from running, instead when it runs you need to check which side is running and which whether the itemstack is passed in a hand that you care about and then act accordingly.
  12. I think you should just create a stationary invisible entity placed at the source block location, give it the model, and ignore the frustum check. Of course that would only take care of the issue of seeing the structure. In both cases, as block model or entity model, you'll have to do some tricky stuff to add collision boxes where necessary.
  13. Yeah, there is a whole system of which entities are "tracked" on each client since the world is so big that it doesn't make sense to have every entity sending info to the client continuously. I have some flying entities where I have to put the range to 8000 because otherwise the disappear if they fly high and also at some distance. And the second parameter is also important as the value of 1 will mean the updates are sent very occasionally, but for fast moving ones you want them sent more frequently.
  14. For fast moving entities, I usually put 80, 10 where you put a 5, 1 in your entity registration. I think your "5" means you'll stop tracking once it is 5 blocks away!
  15. Does it work any better if you apply the leash before you call the sheep spawn? Just a thought, maybe it would sync better that way.
  16. I explained in the beginning. I'm porting from 1.7.10 where I used a custom packet and it was easy to serialize NBT for syncing. Then I saw that data manager had a tag compound serializer, so figured the easiest way to port was to use that. But that got me in trouble because in my custom packet system I was of course saving the packet contents into my NBT field. But with data manager this got complicated because presumably it already stores it and I was essentially instantiating it twice and things got out of sync. But basically NBT was a relic from my previous implementation that I thought would be easy to port since all my methods were already expecting that format. I've broken it all into separate data manager entries now though.
  17. Yay, finally got it working. Honestly, using that entityInit() and data manager is pretty tricky. Don't think i've ever run into so many crashes in a two day session of programming ever. The main points I was missing was that entityInit() was called before my constructor and that my field initializations were happening after the super constructor.
  18. Oh, I was just reading up on constructors and I guess Java initializes class fields in different order than other languanges I'm used to. Apparently they are created AFTER the call to the super constructor. https://stackoverflow.com/questions/20577430/what-is-object-field-initialization-and-constructor-order-in-java So that is a big part of my trouble I think. The entityInit() is called from the inherited Entity constructor which I guess is called before my sync compound is even declared! So basically entityInit() cannot access any class fields...although it is strange then that it could still register the data parameter which is a class field. Let me fix that and see if I'm still having issues with the client sync...
  19. Ahhh! That explains the current crash for the EntityBirdsOfPrey, I actually had previously been using EntityInit() as I thought that was the right place but was having other troubles with the data manager and so I moved it back to the constructor and I must have mistakenly deleted the super call at the same time leaving the stub. However, now that I moved things back to entityInit() I'm back to my original problem: There is still something fishy in the order of the code in my constructor versus entityInit(). The way I understand it should work is that my constructor first calls super constructor which calls my entityInit() which should first call its super-method and then the rest of my constructor code should run. Since my data parameter is a tag compound, I need to initialize the tag compound before the data parameter registration, but that means that the tag compound init has to be in entityInit(). But when I do that, I get a null pointer exception trying to set the first tag. If I move the same code it works much better in the constructor. This fails with null pointer (console error https://gist.github.com/jabelar/8a305ca1d38c9b2893867a2aa4f73374) on the first line of initSyncCompound(): This passes -- same code just moved from entityInit() to constructor:
  20. The best way to debug things like this is to either trace them in debug mode in Eclipse or put a bunch of System.out.println() statements throughout your code and watch the console output to understand how your code is executing. For example, to know that the EntityHorseCart is actually being created you can put a System.out.println("Constructing") statement in the constructor. You should do a similar thing in your render class, maybe putting statements in your doRender() method. When an entity doesn't seem to spawn, it often is spawning but just invisible or sometimes it is in a location like 0, 0, 0 that cannot be seen. But anyway, use print statements in order to figure out which parts of your code are actually running.
  21. Okay, this is really weird. I decided to increment health (which has a vanilla entry into the datamanager) and increment my rearing counter every living update and to also print out both server and client side data manager entries. The health tracks on the client but the rearing counter does not -- in other words, there is a value in my data parameter that is changed on the server but does not get updated on the client! Here is the console output: So why is a value that is in the server data manager and marked dirty never showing up in the client data manager, even though other entries are???
  22. So I wanted to check out the operation of the dataManager a bit more, so in my EntityHerdAnimal in the onLivingUpdate() method I printed out all the entry key-value pairs and whether each entry was marked dirty. The code to print it out was: List<DataEntry<?>> entryList = dataManager.getAll(); System.out.println("On client = "+world.isRemote+" the entity ID "+getEntityId()+" the data manager entry list is: "); entryList.forEach(entry -> System.out.println("key = "+entry.getKey()+" value = "+entry.getValue()+" isDirty = "+entry.isDirty())); And the output was pretty much what I expected, except that EVERY entry is always marked dirty every tick. Here is what the console showed: The last entry shows my NBT tag compound containing some info on the "rearing" animation for the elephant. The rest of the values are built in to the vanilla classes, for example the value 40 is the health entry You can figure out the other value's meaning by looking at the type hierarchy for EntityTameable. Why are all these always dirty? None of the values are changing at this time (the log above goes on and on every tick with same info and all entries marked dirty). I thought that if they were dirty that a packet would be sent, they'd all be marked clean and they'd only be dirty again if the values changed through another set() call...
  23. Further tracing and yes by marking the data manager as dirty, the entity tracker sendMetaData() method will sent to all players tracking a packet SPacketEntityMetadata that takes in the entity ID and the data manager. So I do feel that a packet should be being sent every time I set a value.
  24. With further testing I found that my EntityElephant data manager isn't working either. It isn't crashing, but no information is getting from server to client. It only appeared to work because the codes was running on both sides. So I'm confused -- I thought the data manager was to help sync bits of info to the client like the old data watcher did. But instead it seems that the data watcher is just running independently on both sides... am I missing some method that causes it to actually send the packet? The dataManager.set() method seems to create a notify change as well as marking both the entry and the set as "dirty" so I thought that meant it would send a packet.
  25. What does the whole class look like? Are you using the @ObjectHolder and @Mod.EventBusSubscriber annotations properly on your block registration class?
×
×
  • Create New...

Important Information

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