Jump to content

Recommended Posts

Posted

So i have my mod created, but someone has found an issue. Basically when using my mod with any other mod that allows flight via armor, or ring, or any way, my mod disables flight for ANY other mod out there. For example, my mod adds some armor, more specifically Topaz Armor that can fly with double tapping space bar. Say, I use the ArmorPlus mod with mine which has armor called The Ultimate Armor for example, if I double tap with that armor, I can fly. however if i use my mod with armorplus mod together, my mod still flys with my armor, but disables all flight for ArmorPlus mod, or for that matter any other mod. How can I fix this? I was told to do this but am confused.

 

"he explained that you don't need to (and shouldn't) change the flag every player tick. Just check when armor is equipped and then change the flag then and only then".

 

Here is my Event Handler for Flight for Topaz Armor.

 

http://pastebin.com/eARwJ8A6

 

Any help is greatly appreciated, thank you.

 

Posted

I could be wrong, but I think it would be better to do this on something like an armor item's onUpdate event..by using the PlayerTick event, you're messing with anything any other mod might be using that event for..when you set the value of player.capabilities.allowFlying to false, you're doing this on a global scale..

 

Also..whoever told you that this doesn't need to happen every tick is correct..doing a check every tick should be fine (I would assume)... If it has changed from it's previous state, then update player accordingly

Posted

Okay, for your Item (assuming it extends Item (net.minecraft.item.Item), you can override the onUpdate method which takes the following parameters: ItemStack, World, Entity, int, boolean

 

from Entity you can check that it is an instance of EntityPlayer.

if it is an instance of EntityPlayer, you can get the player's inventory to check if they have the required pieces of armor equipped

if they have all of the required pieces, you can check for capabilities.isFlying and so on...

Posted

You DO need to use the PlayerTickEvent because Armor doesn't tick when it's not worn*, so the only way to remove the flying effect when no longer wearing your armor is via a tick event.

 

The trick to mod compatibility is to set allowFlying to true every tick that it should be true, but only set it to false ONCE when the condition is no longer met. To do that, you need a separate boolean 'wasFlyingAllowed'. This way, you only toggle flying off once, and any other mod that says flying is still allowed sets it during their tick event.

 

Note that it's still not perfect - if your tick event is last to evaluate, there will be one tick in which the player cannot fly and will begin to fall (if you also set #isFlying to false), even though the very next tick they will be allowed to fly again. It's a wonder there isn't yet a universal way to ensure inter-mod flying compatibility (at least that I've heard of), given how many mods add it.

 

* Yes, it still has #onUpdate called while in the player's inventory, but that won't happen if the armor is destroyed, moved to another inventory directly, etc. #onUpdate is not a reliable method of toggling off an ability.

Posted

I was under the impression everything that is in InventoryPlayer is ticked..good to know =D

You are not wrong; where you err is in assuming that armor is always going to remain in InventoryPlayer.

 

I edited in some examples - armor breaks, is tossed or otherwise moved out of inventory directly from the equipment slot, or a mod simply sets it the slot to null or a different item. In all of those cases, the armor will not get a chance to have an update tick after being unequipped, and you'll be unable to toggle off whatever ability you had toggled on.

 

If, however, you were using AttributeModifiers rather than relying on update ticks, then it would be fine. Too bad there isn't an 'allow flying' attribute modifier... hmm... 'flySpeed' as a new SharedMonsterAttribute, anyone? :P

Posted

Sadly I still can't figure this out. Could anyone give me the code needed to solve this issue? I've been at it for hours and can't figure it out. I'm not super smart when it comes to coding, I only know the basics.

Posted

All you need to do is add 'public boolean wasFlyingAllowed = false' to your event handler, set it to true when your armor is all on, and then only disable flying if it's true and not all of your armor is allowed:

// Note: you should check for NULL on all of these or you WILL crash
if (boots.getItem() == SlurpiesDonglesItems.topaz_boots && chestplate.getItem() == SlurpiesDonglesItems.topaz_chestplate && leggings.getItem() == SlurpiesDonglesItems.topaz_leggings && helmet.getItem() == SlurpiesDonglesItems.topaz_helmet) {
    event.player.capabilities.allowFlying = true;
    event.player.fallDistance = 0.0F;
    wasFlyingAllowed = true;
} elseif (wasFlyingAllowed) {
    wasFlyingAllowed = false; // now you won't be constantly setting allowFlying to false
    if (!event.player.capabilities.isCreativeMode) {
        event.player.capabilities.isFlying = false;
        event.player.capabilities.allowFlying = false;
    }
}

Posted

You didn't use the code as I wrote it, and you are using local variables instead of class fields.

 

- wasFlyingAllowed needs to be a class field so that it is remembered from tick to tick rather than being recalculated every tick.

 

- You don't need allowFlying at all - remove it.

 

- You moved your code to disable flying inside of your check for if (allowFlying), meaning that as soon as you are not allowed to fly, it is impossible for your code to disable it...

 

- Please take time to study basic Java and logic:

if (wasFlyingAllowed) {

} else if (wasFlyingAllowed) {  // this is the same condition you just checked - how can it possibly ever run?
  // dead code
}

Posted

If your need is general programming ability rather than specific Forge-wrapper tips, then you should seek out a personal friend or family member who can tutor you in programming/Java. You should never ever ask someone here to write your code for you (remember this forum's description: "This is not Java school").

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
    • Remove rubidium - you are already using embeddium, which is a fork of rubidium
  • Topics

×
×
  • Create New...

Important Information

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