Jump to content

coolAlias

Members
  • Posts

    2805
  • Joined

  • Last visited

Posts posted by coolAlias

  1. Oh yeah, z-coord... lol, dunno about that then.

     

    As for the block metadata and code running twice - you should only ever change data on the SERVER side. If it's important for the client to know about it for whatever reason (e.g. rendering) then Minecraft usually syncs that data automatically. This is the case with setting blocks or block metadata. Never set that on the client.

     

    Many methods are called on both sides, and that's fine, but the server has the final say. @SideOnly is NOT an appropriate solution to this issue - instead, nest your code inside of an `if (!world.isRemote)` check so it only runs on the server, or without the ! to run it on the client (e.g. spawning particles).

  2. Yep - #onBlockActivated is NOT @SideOnly(Side.CLIENT) - you should NEVER add that unless the vanilla or Forge method you are overriding uses it.

     

    In 1.7.10, the client player's y position has their eye height added to it, so that's why you're getting off by 1 issues.

     

    Also, you cannot have local mutable fields in Block or Item classes because there is only one instance of each of them - your 'cooldown' field is effectively static and will be the same for every single block of this type in the game. If you don't mind them all 'cooling down' at the same time, that's fine, but otherwise you'll need a TileEntity.

  3. Also Item has a method specifically designed to help you return a different IIcon / model based on the current use duration:

    @Override
    @SideOnly(Side.CLIENT)
    public IIcon getIcon(ItemStack stack, int renderPass, EntityPlayer player, ItemStack usingItem, int useRemaining) {
        int ticksInUse = stack.getMaxItemUseDuration() - useRemaining;
        // return different IIcon based on how long item has been in use - see vanilla ItemBow for example
    }
    

  4. Really? Well if that's the case, just follow what Jabelar here said. But I seriously remember that you need an IGuiHandler for even just client-only GUIs. Oh well.

    I don't think 'need' is the correct term, but it doesn't hurt anything if you do, and then you can open all of your GUIs using the player#openGui method. Personally, I would recommend having an IGuiHandler for all GUIs, not just Container-based ones.

  5. That's because every API is unique, and all an API really is is some public-facing methods, classes, or interfaces that others can use to interact with your code. E.g. an interface IDoSomething that can be added to any block with the promise that the method #doSomething will be called any time the Block is clicked. That's effectively an "API".

     

    Why do you even want to make an API? Are you expecting other people to write mods that interact with yours, or is it just for fun? What is your API going to provide?

  6. I've heard good things about Tabula, though I've never used it personally and don't know if it's for Mac.

     

    Otherwise, use MCAnimator to create the models and then position your model in various intermediate poses, then cycle through them to create an animation. Jabelar has a pretty good tutorial on that floating around somewhere - find one of his posts and click the link in his signature for his blog.

  7. coolAlias, what you are saying is not always true. Unless there is an underlying mechanism already that separates the two sides into two instances (e.g. with Entities, TileEntities, etc.) fields will not just be magically different between client and server in SinglePlayer.  The two sides run on the same VM, in the same process. If you have an EventHandler somewhere and put a list in it this list will be shared between client & server.

    Yeah, you're right. I was thinking in terms of Entity, but if you have an event handler or similar class on single player (which the OP does...), the class fields will be shared (so even if you only add things to the list on 1 side, the other side will have that same data without packets). Thanks for the correction.

     

    @OP The above could explain why you are getting CME if you are only getting it in Single Player - both client and server threads (and SP is where MC is actually multi-threaded, as Ernio was saying) are iterating over the list. Adding a synchronized block or any kind of Lock should work but could negatively impact performance on single player (you probably won't notice), or using separate collection instances for each thread (again as Ernio suggested).

     

    Still, the best solution is to animate as I described in my previous post, and forget all this tick event business. What you have now is not the best way to animate an entity.

  8. You may not need to bake them at all if you just want to do combine that model / texture with another one that is already baked:

    // in your ISmartItemModel
    IBakedModel model = Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getModelManager().getModel(new ModelResourceLocation("yourmodid:name_of_the_model_you_want", "inventory"));
    
    // now you can add the model's quads to the current smart item model, e.g.:
    this.quads.addAll(model.getGeneralQuads());
    

    I use something similar to combine the front and back of my shield models and only the front one is registered and baked.

     

    Actually, that reminds me: I DID add those additional names as variants of my item, even though they are not themselves real items (they don't exist anywhere and can't be had by any means).

     

    For one or all of your Attachment item classes, try adding the extra names as variants:

    ModelBakery.addVariantName(YourAttachmentItem, real_attachment_name, gun_name_plus_attachment_name_1, etc.);
    

     

    Also, instanceof checks for null, so the following are functionally equivalent:

    if (object != null && object instanceof Something)
    if (object instanceof Something)
    

  9. @Ernio I don't know where you're getting all this multi-threading stuff from - MC is not really multi-threaded except for the network, and that is, well... not well done. The server and client run as separate applications (unless on single player), not threads, so synchronizing a block (which does the same thing as a lock) in one application has no effect on the other application.

     

    Even in single player, having a single array or Collection that operates on both sides, there is already a separate instance of it on each side. Otherwise doing:

    List list = new ArrayList();
    
    someMethod(World world) {
      if (world.isRemote) {
        list.add("you won't see this on the server!");
      } else {
        print list to screen; // nothing will ever show up here because the server list is separate from the client list
      }
    }
    

     

    Anyway, @OP Animations are usually triggered by the server, but only run on the client. What that means is, for example, an entity performs an attack on the server (the trigger) which sends a notification to the client saying "I (the entity) am attacking now" and the client then starts the animation timer for the attack animation.

     

    I don't know how MCAnimator is set up or expects things to be handled, but really you shouldn't need any sort of Collection to handle animating entities - that should be done in the Entity class (for the triggers and possibly a timer) and the entity's Render / Model class (for the actual animations).

     

    For a good example of this, check out the Iron Golem, specifically its attack on the server and how that triggers a client-side animation by using World#setEntityState in combination with the entity's #handleHealthUpdate methods, a class field for the timer that gets set on both sides, and a Model class that uses that timer to change the arm position.

  10. Well, that's pretty bizarre. Using an Iterator to remove elements should generally protect you from CME in this type of scenario - the only other thing I can think of that you can try is to surround your current list traversal with a synchronized block:

    synchronized (activeEntities) {
       // iterator code and iterate over list
    }
    

    That will prevent any other methods or threads from accessing the activeEntities List until that code block completes.

     

    Perhaps someone with more Java knowledge will be able to explain your problem, as I am at the end of mine with respect to CME :\

  11. Just another tidbit: ReflectionHelper#getPrivateValue can take the field index instead of names, e.g.:

    // field index is zero-indexed, so n-1
    Object o = ReflectionHelper.getPrivateValue(RenderGlobal.class, renderGlobal, 13);
    // you'll need to check type and cast to get the actual value
    

    Granted, it's less readable, but sometimes you just want something quick and dirty, e.g. for initial testing (especially if there are only a handful of fields - RenderGlobal is not a good use case).

  12. You are not using the Iterator to remove the element... -.-

     

    Please, search 'removing Collection element with Iterator' or some such to learn how to use them to remove entries from a Collection.

     

    Also, you won't need a removableEntities list - you can remove the entry directly when found (when using the Iterator correctly).

  13. Ok heres what I made with Iterators:

     

     

    			if(event.phase == Phase.START) {
    			for(IMCAnimatedEntity entity : activeEntities) {
    				entity.getAnimationHandler().animationsUpdate();
    
    				if(((Entity)entity).isDead) {
    					removableEntities.add(entity);
    				}
    			}
    
    			for(IMCAnimatedEntity entity : removableEntities) {
    				activeEntities.remove(entity);
    			}
    			removableEntities.clear();
    		}

     

    o.0 I don't see any Iterator in there at all, just a foreach loop. Please, if you don't know what something is, search before you ask. There are literally thousands of pages discussing how to use Iterators in Java that you should read rather than wasting our time here.

     

    So the client runs and starts deleting files that the server is currently iterating through? Is that correct?

    variables exist separately in Minecraft client vs. server because they are (or effectively are) separate applications, so if you had a List that existed on both sides, you could modify it to your heart's content on one side without the other side ever being affected by it.

    How is that not clear? And "files" ?! You're not handling any files at all in the code you posted...

  14. CME can occur even on a single-threaded application, so it is not necessarily a threading issue; in fact, variables exist separately in Minecraft client vs. server because they are (or effectively are) separate applications, so if you had a List that existed on both sides, you could modify it to your heart's content on one side without the other side ever being affected by it. That's why you need packets to communicate between the two.

     

    Anyway, you can safely remove elements using Iterators, but not the standard List methods. A quick search on Google brings up lots of information; e.g. this SO question which should help your specific situation.

     

    Other solutions are to make a copy of the collection, but I usually prefer iterators when I wish to remove elements mid-iteration.

  15. I did, in fact I searched those up and down before coming here. I found LayerRenderer but what is it and how do I use it?

    Did you look at the code for rendering bipeds, i.e. RenderBiped, or any non-abstract render class? RenderBiped has a couple layers and should provide more than enough of an example to see what they are and how to use them.

  16. #mouseReleased's 3rd parameter is the button that was released. To find out what the values are, put System.out.println("Released: " + state) in your method and play around in your GUI. 'Button' or 'released' would probably be better names than 'state' for that parameter.

×
×
  • Create New...

Important Information

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