Jump to content
Search In
  • More options...
Find results that contain...
Find results in...


  • Posts

  • Joined

  • Last visited

Everything posted by Alekseyev

  1. Bumping in hope of someone having an idea
  2. You create a new Capability every time you call getCapability. Return your already existing instance instead. You're trying to cast the LazyOptional of the capability to the capability itself. Instead you should retrieve it by using one the methods that exist for that purpose. I was linked this article some time ago by helpful persons, and it helped me greatly in understanding LazyOptionals (which function mostly the same as regular Optionals) https://www.baeldung.com/java-optional
  3. Hi, I ran into a problem: The night vision's effect of brightening up the surroundings is handled in LightTexture#updateLightmap(float partialTicks) and checks for the potion effect, after which a value (usually 1, if the effect is about to expire 0.7 + a sinus curve) is retrieved. How would I implement my own night vision effect, say, at lower intensity? I don't think it's possible to change that vanilla method to account for another check.
  4. Considering how you updated your post for 1.12, I thought you might want to do it for 1.14 as well: In 1.14, the WorkbenchContainer also has a "player" field, so the detour over the slot is no longer needed. Instead of using reflection, I used access transformers for the CraftingInventory's container field (called field_70465_c) as well as the PlayerContainer's and WorkbenchContainer's player field: In accesstransformer.cfg: public net.minecraft.inventory.CraftingInventory field_70465_c # container of CraftingInventory, used for conditional crafing recipes public net.minecraft.inventory.container.PlayerContainer field_82862_h # player of PlayerContainer, used for conditional crafting recipes public net.minecraft.inventory.container.WorkbenchContainer field_192390_i # player of WorkbenchContainer, used for conditional crafting recipes The findPlayer method can then be changed as follows: private static PlayerEntity findPlayer(CraftingInventory inv) { try { Container container = inv.field_70465_c; if (container instanceof PlayerContainer) { return ((PlayerContainer) container).player; } else if (container instanceof WorkbenchContainer) { return ((WorkbenchContainer) container).player; } else { // don't know the player return null; } } catch (Exception e) { throw Throwables.propagate(e); } }
  5. Oh wow, I am dumb. No idea how I missed that file on Github. I always forget about how you don't have to import things from the same package...
  6. @Choonster in your TestMod3 you use a "RecipeUtil.ShapedPrimer", but you don't seem to import it anywhere, nor can I find such a file in the minecraft/forge sources.
  7. Which would be +20 ticks per second if your game runs at full speed, and less if the processor can't keep up with all the things it has to compute.
  8. Could be fixed for the most part by setting the getRenderLayer to CUTOUT or CUTOUT_MIPPED.
  9. You could also have the inventoryTick function check the modulo of ticksExisted of the entity so that the rest of the code only fires every x ticks.
  10. Are you sure that your texture has transparent areas? Could be missing an alpha channel in the PNG.
  11. Hi, I designed a custom block model and got it to load in the world. However, I am facing two issues: 1: The floor below the block is not rendered. 2: The lighting on the model itself is broken on some faces (notably the upper and lower parts of those at an angle. (The textures and z-fighting will be fixed later, but that's not so important right now.)
  12. Would it also be an option to replace the Item Set with one of your own choice via reflection?
  13. I thought about the following: Instead of checking the charge value and being updated on it, the client just has a boolean for "1000 or higher". The server then only sends an update packet whenever the charge value crosses this treshold. However, there is a problem: I also want the charge to be displayed on the HUD later (in the form of a bar of varying size), and to calculate that size, you'd need the value again...
  14. Hi, I can successfully use LivingHurtEvent or LivingDamageEvent to set damage caused by a certain source to zero or cancel the event right away. However, other effects associated with damage still play, notably the hurt sound and the screenshake. How would I go about removing these depending on the damage source, say, for example, drowning or being on fire?
  15. HarvestCheck is fired between the destruction of a block and the (optional) creation of drops. I am not 100% sure whether it only fires for blocks with a harvest level of 1 or higher, but I remember something like this. It definitely also includes ordinary blocks like stone or snow, that require a tool to be collected. Haven't used the other event myself yet and no documemtation at hand.
  16. Hey there, I have a capability with a boolean (active status) and an integer value (a charge value). I want to check this data for many effects and events. Here are my current cases: BreakSpeed and Jump Height (but planning to add more later on, such as attack damage or mob behaviour) I want to make it so that when the boolean is active, the player's block breaking speed is doubled or jump height increased. This works fine. However, I also want to reduce the charge value while doing this. When simply using the code further down, a desync in the values known by the client and by the server starts to manifest after prolonged usage, from both the block breaking and jump height. The debug chat line also appears twice per side for some reason, with the second time showing the already incremented charge value. This makes me wonder: What is the best way to handle capability data like this? Since some data is handled by the server and other data by the client (such as movement), the data would have to be present on both, but considering that the charge is modified so highly frequently, sending a packet every frame surely can't be the right way to handle it? @SubscribeEvent public void breakingSpeed(net.minecraftforge.event.entity.player.PlayerEvent.BreakSpeed event) { if (getBioData(player).getMaskActive()) { Item mask = player.inventory.armorItemInSlot(3).getItem(); if (mask == ItemInit.KANOHI_PAKARI) { event.setNewSpeed(event.getNewSpeed() * 2); getBioData(player).modifyMaskCharge(-5); if (player.ticksExisted % 20 == 0) { player.sendStatusMessage(new TextComponentString(TextFormatting.DARK_GRAY + "Speeds: New: " + event.getNewSpeed() + " Old: " + event.getOriginalSpeed()), false); } } } } @SubscribeEvent public void jumpEffect(LivingEvent.LivingJumpEvent event) { if (event.getEntity() instanceof EntityPlayer) { EntityPlayer evPlayer = (EntityPlayer)event.getEntity(); if (getBioData(evPlayer).getMaskActive() && evPlayer.inventory.armorItemInSlot(3).getItem() == ItemInit.KANOHI_MIRU && getBioData(evPlayer).getMaskCharge() >= 1000) { evPlayer.motionY += 0.7D; evPlayer.motionX *= 4.0D; evPlayer.motionZ *= 4.0D; getBioData(evPlayer).modifyMaskCharge(-1000); } } } @SubscribeEvent public void playerTick(TickEvent.PlayerTickEvent event) { if (!(player.inventory.armorItemInSlot(3).getItem() instanceof Kanohi) && getBioData(player).getMaskActive() == true) { getBioData(player).setMaskActive(false); player.sendStatusMessage(new TextComponentString(TextFormatting.RED + event.side.name() + " Mask unequipped, setting to: " + (getBioData(player).getMaskActive() ? "On" : "Off")), false); } if (getBioData(player).getMaskActive()) { Item mask = player.inventory.armorItemInSlot(3).getItem(); if (mask == ItemInit.KANOHI_MIRU) { player.fallDistance = 0; } } else { getBioData(player).modifyMaskCharge(+10); //Increasing charge with mask deactivated } if (player.ticksExisted % 100 == 0) { player.sendStatusMessage(new TextComponentString(TextFormatting.DARK_RED + event.side.name() + " Mask: " + (getBioData(player).getMaskActive() ? "On" : "Off") + " Charge: " + getBioData(player).getMaskCharge()), false); } } public class DefaultBioPlayerDataHandler implements IBioPlayerDataHandler { private BioElements element; private Boolean maskActive = false; private int maskCharge = 10000; private final int maxCharge = 10000; @Override public BioElements getElement() { return element; } @Override public void setElement(BioElements element) { this.element = element; } @Override public void removeElement() { this.element = BioElements.NONE; } @Override public Boolean getMaskActive() { return maskActive; } @Override public void setMaskActive(Boolean status) { this.maskActive = status; } @Override public int getMaskCharge() { return this.maskCharge; } @Override public void setMaskCharge(int charge) { this.maskCharge = charge; } @Override public void modifyMaskCharge(int modifier) { if (maskCharge + modifier >= 0) { if (maskCharge + modifier <= maxCharge) { maskCharge = maskCharge + modifier; } else { maskCharge = maxCharge; } } else { maskCharge = 0; maskActive = false; } } }
  17. Sorry, sometimes I'm dumb. I was assuming that if there has to be a parameterless constructor, that one would be used in the sending process somehow and you would be unable to use your pre-created object. I would dare to say that I know basic java pretty well, it's using someone else's hooks and libraries and whatnot (in this case Forge) what gets me all the time. :s
  18. How do I supply the info to the packet, then? --------------------------------------------------- Thanks for the heads up, I will keep it in mind for the future. This particular case was just for easy testing anyway and will be removed afterwards. I thought about simply using an ordinal and a single byte, since the amount of enum values will never exceed 256 anyway. I will look into fixing this as soon as the packet sending itself works.
  19. Hi all, after quite some time away I finally got back to fixing a long-standing issue within my mod in progress. (See here) I was advised to send the capability data to the server via a packet, and therefore set out to that. I came across this tutorial: https://wiki.mcjty.eu/modding/index.php?title=Networking-1.12 and used that to test out how packets work. The example function that was provided works flawlessly. However, when I tried to use another packet to update the needed data, I received a crash. Here's the crash log. And here are my relevant classes: Event Subscriber @SideOnly(Side.CLIENT) @SubscribeEvent(priority=EventPriority.NORMAL, receiveCanceled=true) public static void onKeyInput(InputEvent.KeyInputEvent event) { System.out.println("Key Input Event"); KeyBinding[] keyBindings = ClientProxy.keyBindings; // crashes if (keyBindings[KEY_TEST].isPressed()) { System.out.println("Key binding =" + keyBindings[KEY_TEST].getKeyDescription()); PacketHandler.INSTANCE.sendToServer(new PacketUpdateElement(BioElements.WATER)); } //Works fine if (keyBindings[KEY_GET_BLOCK].isPressed()) { System.out.println("Key binding =" + keyBindings[KEY_GET_BLOCK].getKeyDescription()); PacketHandler.INSTANCE.sendToServer(new PacketSendKey()); } } Packet public class PacketUpdateElement implements IMessage { private BioElements element; @Override public void fromBytes(ByteBuf buf) { try { byte[] bytes = new byte[buf.readableBytes()]; buf.readBytes(bytes); element = BioElements.valueOf(new String(bytes)); } catch (IllegalArgumentException e) // If no matching String is found in the enum, an IllegalArgumentException will be thrown { System.out.println("An error occurred: " + e.getMessage()); element = BioElements.NONE; System.out.println("Element was set to NONE."); } } @Override public void toBytes(ByteBuf buf) { buf.writeBytes(element.name().getBytes()); } public PacketUpdateElement(BioElements element) { this.element = element; } public static class Handler implements IMessageHandler<PacketUpdateElement, IMessage> { @Override public IMessage onMessage(PacketUpdateElement message, MessageContext context) { FMLCommonHandler.instance().getWorldThread(context.netHandler).addScheduledTask(() -> handle(message, context)); return null; } private void handle(PacketUpdateElement message, MessageContext context) { EntityPlayerMP playerEntity = context.getServerHandler().player; if (playerEntity.hasCapability(CAPABILITY_BIO_PLAYER_DATA, null)) { playerEntity.getCapability(CAPABILITY_BIO_PLAYER_DATA, null).setElement(message.element); } playerEntity.sendStatusMessage(new TextComponentString(TextFormatting.GREEN + "Selected element from packet: " + message.element.name()), false); } } } Packet handler public class PacketHandler { private static int packetId = 0; public static SimpleNetworkWrapper INSTANCE = null; public PacketHandler() { } public static int nextID() { return packetId++; } public static void registerMessages(String channelName) { INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(channelName); registerMessages(); } public static void registerMessages() { // Register messages which are sent from the client to the server here: INSTANCE.registerMessage(PacketSendKey.Handler.class, PacketSendKey.class, nextID(), Side.SERVER); INSTANCE.registerMessage(PacketUpdateElement.Handler.class, PacketUpdateElement.class, nextID(), Side.SERVER); } } PacketHandler.registerMessages("biomod"); is fired in the FMLInitializationEvent event subscriber. I tried figuring out the issue on my own, but had no luck so far.
  20. I'd like to have an effect where the environment is rendered a bit lighter, but not fully bright as it would be with night vision. (Maybe everything about comparable to 2 light levels brighter) However, I couldn't find the implementation of the night vision effect as a reference. Can someone point me in the right direction? (Any other advice is also welcome of course.)
  21. EDIT: I just realised that I did the UUID thing wrong. Working on this... EDIT2: It was indeed the issue. To anyone else coming across this: DO NOT use the player UUID for the modifier, use a custom one per modifier instead. For example, use UUID.fromString("<string goes here>") to generate it. Hello, I have a problem: After reading up on other threads, I was made aware of the fact that instead of setting the base value of a SharedMonsterAttribute, it is better to add a modifier to it to keep compatibility. This effect is applied to every player once after joining the world. However, if I close the game and then re-launch it and join the same world again, the old effect does not seem to be deleted - in the case of the health effect (FIRE), the HP went back to 10 hearts after joining the world a third time, only to then jump to 13. Intended would be that the modifier can only be applied once at a time, for a maximum of 11 hearts (22 HP). This is the code in use: // Attribute modifiers - these serve to define modifiers (multiplicative for speed, additive for health; depends on operationIn) AttributeModifier moveSpeedBonus = new AttributeModifier(evPlayer.getUniqueID(),"waterAirMoveBonus",0.15D,2); AttributeModifier moveSpeedMalus = new AttributeModifier(evPlayer.getUniqueID(),"earthMoveMalus",-0.05D,2); AttributeModifier healthBonus = new AttributeModifier(evPlayer.getUniqueID(),"fireHealthBonus",2.0D,0); AttributeModifier healthMalus = new AttributeModifier(evPlayer.getUniqueID(),"waterHealthMalus",-2.0D,0); // Get rid of any possible modifiers if (evPlayer.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).hasModifier(moveSpeedBonus)) { evPlayer.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).removeModifier(moveSpeedBonus); } if (evPlayer.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).hasModifier(moveSpeedMalus)) { evPlayer.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).removeModifier(moveSpeedMalus); } if (evPlayer.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).hasModifier(healthBonus)) { evPlayer.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).removeModifier(healthBonus); } if (evPlayer.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).hasModifier(healthMalus)) { evPlayer.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).removeModifier(healthMalus); } // Apply where needed switch(element) { case FIRE: evPlayer.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).applyModifier(healthBonus); if (evPlayer.getHealth() == evPlayer.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).getBaseValue()) { evPlayer.setHealth(evPlayer.getHealth() + 2); //This is to heal the player up by the 2 HP/1 heart if the element was just switched to. } break; case AIR: evPlayer.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).applyModifier(moveSpeedBonus); break; case WATER: evPlayer.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).applyModifier(healthMalus); evPlayer.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).applyModifier(moveSpeedBonus); break; case EARTH: evPlayer.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).applyModifier(moveSpeedMalus); break; default: break; }
  22. Oh, I thought race conditions only come into play if two threads try to modify the same value - in this case, the 2nd thread would change something that is never going to be changed by the first thread. But I may very much be wrong... I had this thing in university once, but it's been a while. Alright. In retrospective I should have thought about that myself, with all the other stuff in the vanilla classes that gets called all the time... I'll get into that soon. Also congrats on 40k posts!
  23. Oh, that is interesting! I would have expected it to fail every time, Cadiboo's post sounded very absolute. Do you have a different suggestion? I'd guess that handling it in playerTickEvent would add an unnecessary performance impact, adding a check to every single tick even though the condition would only be met once.
  24. I'm afraid I can, because it does work when using this thread. When I don't create/run it, the capability does not get set. It's not giving any errors either.
  25. I solved this problem the following way: PlayerLoggedInEvent creates a new runnable that does the following: @Override public void run() { try { while (Minecraft.getMinecraft().player == null) { System.out.println("player is null, sleeping for 2 seconds"); Thread.sleep(2000); } getHandler(Minecraft.getMinecraft().player).setElement(element); } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println("Runnable finished"); } It appears to work, but I'm not super sure how clean the while + sleep loop is. Any suggestions on improving the code?
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.