Jump to content

Recommended Posts

Posted

Hey again. I've managed to succesfully implement a few different capabilities. However when I open a world the Server gets the correct values while my client doesn't. To solve this I thought I'd implement a packet that sends NBT data to the client and uses my Capabilities wrapper to set the correct values.

 

The error I get is the following: 

java.lang.ClassCastException: net.minecraft.client.network.NetHandlerPlayClient cannot be cast to net.minecraft.network.NetHandlerPlayServer
	at net.minecraftforge.fml.common.network.simpleimpl.MessageContext.getServerHandler(MessageContext.java:55) ~[MessageContext.class:?]
	at com.cheese.rpvp.capabilities.synchers.BarMessage$MessageHandler.onMessage(BarMessage.java:46) ~[BarMessage$MessageHandler.class:?]
	at com.cheese.rpvp.capabilities.synchers.BarMessage$MessageHandler.onMessage(BarMessage.java:38) ~[BarMessage$MessageHandler.class:?]
	at net.minecraftforge.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:56) ~[SimpleChannelHandlerWrapper.class:?]
	at net.minecraftforge.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:36) ~[SimpleChannelHandlerWrapper.class:?]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) ~[SimpleChannelInboundHandler.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) ~[AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) ~[AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[MessageToMessageDecoder.class:4.0.23.Final]
	at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) ~[AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) ~[AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787) ~[DefaultChannelPipeline.class:4.0.23.Final]
	at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:4.0.23.Final]
	at net.minecraftforge.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:109) [FMLProxyPacket.class:?]
	at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:157) [NetworkManager.class:?]
	at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:51) [NetworkManager.class:?]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [SimpleChannelInboundHandler.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.handleClientSideCustomPacket(NetworkDispatcher.java:410) [NetworkDispatcher.class:?]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:276) [NetworkDispatcher.class:?]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:73) [NetworkDispatcher.class:?]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [SimpleChannelInboundHandler.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787) [DefaultChannelPipeline.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel.finishPeerRead(LocalChannel.java:326) [LocalChannel.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel.access$400(LocalChannel.java:45) [LocalChannel.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel$5.run(LocalChannel.java:312) [LocalChannel$5.class:4.0.23.Final]
	at io.netty.channel.local.LocalEventLoop.run(LocalEventLoop.java:33) [LocalEventLoop.class:4.0.23.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [SingleThreadEventExecutor$2.class:4.0.23.Final]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_144]

 

My classes are as follows: 

package com.cheese.rpvp.capabilities.synchers;

import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;

public class BarPacketHandler {

    public static final SimpleNetworkWrapper barWrapper = NetworkRegistry.INSTANCE.newSimpleChannel("rpvp");

}

This package defines my simpleChannel named rpvp after my client info. I create an instance of this class in my Main class with 

   public static BarPacketHandler packetHandler;

and then register it in my commonProxy like so:

BarPacketHandler.barWrapper.registerMessage(BarMessage.MessageHandler.class, BarMessage.class, 1, Side.CLIENT);

 

My goal here is to send a packet from the server (Since the server has the correct values) and pass them on to the client. Since the client needs to be updated. 

 

I subscribed an Event for PlayerLoggedInEvent that will get my Capability and save all relevant info to be updated to an NBTTagCompound and then calls the sendTo method from my Message class. 

    @SubscribeEvent
    public void loggedIn(PlayerLoggedInEvent event){
        if(!event.player.worldObj.isRemote) {
            if (event.player.hasCapability(CAPABILITY_BAR, EnumFacing.DOWN)) {
                final IBarHandler instance = getHandler(event.player);
                final NBTTagCompound tag = new NBTTagCompound();
                tag.setInteger("mana", instance.getMana());
                tag.setInteger("health", instance.getHealth());
                tag.setInteger("fatigue", instance.getFatigue());
                tag.setInteger("maxhealth", instance.getMaxHealth());
                tag.setInteger("maxmana", instance.getMaxMana());
                Main.packetHandler.barWrapper.sendTo(new BarMessage(tag), (EntityPlayerMP)event.player);
                System.out.println("Message sent");
            }
        }
    }

 

Then finally we have the actual BarMessage class with an inner class "MessageHandler". Both have the default method, so that can't be the error. 

 

public class BarMessage implements IMessage {
    public BarMessage(){}
    private NBTTagCompound toSend;
    public BarMessage(NBTTagCompound tag){
        this.toSend = tag;
    }

    @Override
    public void toBytes(ByteBuf buf) {
        System.out.println("toBytes called");
        ByteBufUtils.writeTag(buf, this.toSend);
    }

    @Override
    public void fromBytes(ByteBuf buf) {
        System.out.println("frombytes called");
        this.toSend = ByteBufUtils.readTag(buf);
    }
    public NBTTagCompound getTag(){
        return toSend;
    }

    public static class MessageHandler implements IMessageHandler<BarMessage, IMessage> {

        public MessageHandler(){}

        @Override
        public IMessage onMessage(BarMessage content, MessageContext ctx) {
            System.out.println("messagehandler called");

            EntityPlayerMP serverPlayer = ctx.getServerHandler().playerEntity;
            final IBarHandler handler = getHandler(serverPlayer);
            NBTTagCompound tag = content.toSend;
            handler.setMana(tag.getInteger("mana"));
            handler.setMaxMana(tag.getInteger("maxmana"));
            handler.setHealth(tag.getInteger("health"));
            handler.setMaxHealth(tag.getInteger("maxhealth"));
            handler.setFatigue(tag.getInteger("fatigue"));

            return null;
        }
    }
}

 

I have also tried a Variant of the onMessage where I've set content and ctx to final and tried to make an inner class that uses a scheduled task to set these things, but I assumed that since I'm not influencing the world directly it shouldn't be a problem. 

 

Now the main Issue 

I examined the MessageContext class, which returns the nethandler. Somewhere in my code I've somehow set my nethandler to NetHandlerPlayClient, and when I try to cast it using the getServerHandler it crashes since I only have the NetHandlerPlayClient.

 

I know I must be making some simple mistake that I overlooked, I've googled for a few hours now and It's driving me crazy.

 

I've tried to find a way to access playerEntity outside of the ctx, but that didn't work. I need playerEntity to pass to my getHandler(playerEntity) so I can call the methods for setting my Capabilities, the server sends the Target player with the message. so the Packet gets executed on the Client. I assumed that since I was running the handler on the client I could somehow use

 final IBarHandler handler = Minecraft.getMinecraft().thePlayer().GetCapability(CAPABILITY_BAR);

But that returned a nullpointer exception.

 

I've followed the documentation at https://mcforge.readthedocs.io/en/latest/networking/simpleimpl/ to the T, I don't quite understand what I'm doing wrong here, or what I could do to improve. Some hints would be appreciated.

Posted (edited)

The Nullpointer exception only occurs when I try to register an entity from Minecraft.GetMinecraft.theplayer.getCapability instead of 

PlayerEntityMP player = ctx.getServer etc. etc.

 

java.lang.NullPointerException
	at com.cheese.rpvp.capabilities.synchers.BarMessage$MessageHandler.onMessage(BarMessage.java:47) ~[BarMessage$MessageHandler.class:?]
	at com.cheese.rpvp.capabilities.synchers.BarMessage$MessageHandler.onMessage(BarMessage.java:40) ~[BarMessage$MessageHandler.class:?]
	at net.minecraftforge.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:56) ~[SimpleChannelHandlerWrapper.class:?]
	at net.minecraftforge.fml.common.network.simpleimpl.SimpleChannelHandlerWrapper.channelRead0(SimpleChannelHandlerWrapper.java:36) ~[SimpleChannelHandlerWrapper.class:?]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) ~[SimpleChannelInboundHandler.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) ~[AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) ~[AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[MessageToMessageDecoder.class:4.0.23.Final]
	at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) ~[AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) ~[AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787) ~[DefaultChannelPipeline.class:4.0.23.Final]
	at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:4.0.23.Final]
	at net.minecraftforge.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:109) [FMLProxyPacket.class:?]
	at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:157) [NetworkManager.class:?]
	at net.minecraft.network.NetworkManager.channelRead0(NetworkManager.java:51) [NetworkManager.class:?]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [SimpleChannelInboundHandler.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.handleClientSideCustomPacket(NetworkDispatcher.java:410) [NetworkDispatcher.class:?]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:276) [NetworkDispatcher.class:?]
	at net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.channelRead0(NetworkDispatcher.java:73) [NetworkDispatcher.class:?]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [SimpleChannelInboundHandler.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319) [AbstractChannelHandlerContext.class:4.0.23.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787) [DefaultChannelPipeline.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel.finishPeerRead(LocalChannel.java:326) [LocalChannel.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel.access$400(LocalChannel.java:45) [LocalChannel.class:4.0.23.Final]
	at io.netty.channel.local.LocalChannel$5.run(LocalChannel.java:312) [LocalChannel$5.class:4.0.23.Final]
	at io.netty.channel.local.LocalEventLoop.run(LocalEventLoop.java:33) [LocalEventLoop.class:4.0.23.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [SingleThreadEventExecutor$2.class:4.0.23.Final]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_144]

 

My Capability is registered in my main class in the preInit as such:


        CustomDataHandlerBar.register();

which obviously tells you nothing. the Barhandler is 

public class CustomDataHandlerBar {

    @CapabilityInject(IBarHandler.class)
    public static final Capability<IBarHandler> CAPABILITY_BAR = null;

    public static void register(){
        CapabilityManager.INSTANCE.register(IBarHandler.class, new Storage(), DefaultBarHandler.class);
        MinecraftForge.EVENT_BUS.register(new CustomDataHandlerBar());
    }

    @SubscribeEvent
    public void attachCapabilities(AttachCapabilitiesEvent<Entity> event){
        if(event.getObject() instanceof EntityPlayer)
            event.addCapability(new ResourceLocation(Main.MODID, "BARS"), new BarProvider());


    }
    @SubscribeEvent
    public void clonePlayer(PlayerEvent.Clone event){

        final IBarHandler original = getHandler(event.getOriginal());
        final IBarHandler clone = getHandler(event.getEntity());
        clone.setMana(original.getMana());
        clone.setMaxMana(original.getMaxMana());
        clone.setHealth(original.getHealth());
        clone.setMaxHealth(original.getMaxHealth());
        clone.setFatigue(original.getFatigue());
    }

    @SubscribeEvent
    public void loggedIn(PlayerLoggedInEvent event){
        if(!event.player.worldObj.isRemote) {
            if (event.player.hasCapability(CAPABILITY_BAR, EnumFacing.DOWN)) {
                final IBarHandler instance = getHandler(event.player);
                final NBTTagCompound tag = new NBTTagCompound();
                tag.setInteger("mana", instance.getMana());
                tag.setInteger("health", instance.getHealth());
                tag.setInteger("fatigue", instance.getFatigue());
                tag.setInteger("maxhealth", instance.getMaxHealth());
                tag.setInteger("maxmana", instance.getMaxMana());
                Main.packetHandler.barWrapper.sendTo(new BarMessage(tag), (EntityPlayerMP)event.player);
                System.out.println("Message sent");
            }
        }
    }

    public static IBarHandler getHandler(Entity entity){
            if(entity.hasCapability(CAPABILITY_BAR, EnumFacing.DOWN)){
                System.out.println("Player has capability");
                return entity.getCapability(CAPABILITY_BAR, EnumFacing.DOWN);
            }
        return null;
    }


}

 

I'm able to interact with the Capability and I'm able to set different values using items and equipment and such. I'm not sure if the problem lies with the Capability system.  Though I'm not entirely sure why the server end saves my information properly yet the Client doesn't synchronise with it.  The Forge classes are pretty complex for someone with only a year of Java experience and there's not a lot of online knowledge to find on the current version and what to use, I'm mostly just going by feel and the official docs, which also don't cover much.

 

That's why I'm creating the packet, to keep the client synchronized and to learn how to create packets for the future.

 

Also, when I comment out the Capabilities stuff in the original entityplayerMP = method I'm still getting the same Can't cast error. 

Edited by oldcheese
clarification.
Posted (edited)

 

Quote

 

Warning

As of Minecraft 1.8 packets are by default handled on the network thread.

That means that your IMessageHandler can not interact with most game objects directly. Minecraft provides a convenient way to make your code execute on the main thread instead using IThreadListener.addScheduledTask.

The way to obtain an IThreadListener is using either the Minecraft instance (client side) or a WorldServer instance (server side). The code above shows an example of this by getting a WorldServer instance from an EntityPlayerMP.

 

http://mcforge.readthedocs.io/en/latest/networking/simpleimpl/

Edited by Draco18s
  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
2 minutes ago, Draco18s said:

 

Welp. That's it. 

 

I've tried to change it to a similar code. But I was using ctx instead of Minecraft.GetMinecraft to initiate my IthreadListener.

 

It seems like every time I get stuck on something for multiple hours it turns out to be a big oversight I should've noticed.

 

 

For future readers who run into my topic. The final code for my onMessage ended up being 

 

        @Override
        public IMessage onMessage(final BarMessage content,final MessageContext ctx) {

            IThreadListener myThread = Minecraft.getMinecraft();
            myThread.addScheduledTask(new Runnable(){
                @Override
                public void run(){
                    System.out.println("messagehandler called");
                    final IBarHandler handler = Minecraft.getMinecraft().thePlayer.getCapability(CAPABILITY_BAR, EnumFacing.DOWN);
                    NBTTagCompound tag = content.toSend;
                    handler.setMana(tag.getInteger("mana"));
                    handler.setMaxMana(tag.getInteger("maxmana"));
                    handler.setHealth(tag.getInteger("health"));
                    handler.setMaxHealth(tag.getInteger("maxhealth"));
                    handler.setFatigue(tag.getInteger("fatigue"));

                }
            });
                return null;
        }

 

 

Thanks for the help everyone.

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.