Jump to content

[1.10.2] [SOLVED] Saving additional information to chunk data


Recommended Posts

Posted (edited)
22 hours ago, Choonster said:

 

Any mod that displays an energy value on the client needs to sync it somehow.

 

If it's an energy bar in a GUI, this is usually handled through the Container (which syncs the value when it changes). If it's rendered outside of a GUI, it could either be always synced when the value changes or synced on demand when the value needs to be rendered.

Ok, I got the capability system now implemented. 

 

Does the ChunkWatchEvent.Watch gets only called once, for example the player goes into this chunk and the event gets called and then never again until the player goes into this chunk again? So it does not get called like every 20 ticks when a player is in this chunk.

 

I'm also wondering how I should access my capability from a block to let this block update the value stored in the chunk, as I've only worked with capabilities where the data is directly saved to the block and thus every block had it own instance of in that case the EnergyStorage class.

And how do I access the value stored in the chunk in events like CropGrowEvent or SaplingGrowTreeEvent to do something within those events when the value reaches a critical point.

Should I just do something like this:

final IChunkEnergy chunkEnergy = getChunkEnergy(player.getEntityWorld(), event.getChunk());

 

Edited by Bektor

Developer of Primeval Forest.

Posted
20 minutes ago, Bektor said:

Does the ChunkWatchEvent.Watch gets only called once, for example the player goes into this chunk and the event gets called and then never again until the player goes into this chunk again? So it does not get called like every 20 ticks when a player is in this chunk.

 

It gets fired once when the player starts watching the chunk and won't be fired for that player and chunk again until they stop watching it and then start watching it again. It's not fired constantly while a player is in the chunk.

 

23 minutes ago, Bektor said:

I'm also wondering how I should access my capability from a block to let this block update the value stored in the chunk, as I've only worked with capabilities where the data is directly saved to the block and thus every block had it own instance of in that case the EnergyStorage class.

And how do I access the value stored in the chunk in events like CropGrowEvent or SaplingGrowTreeEvent to do something within those events when the value reaches a critical point.

 

Access the holder capability through the World and then use it to get the energy storage for the chunk. I created helper methods in CapabilityChunkEnergy to get the IChunkEnergy for a Chunk or World and ChunkPos.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted
2 hours ago, Choonster said:

 

It gets fired once when the player starts watching the chunk and won't be fired for that player and chunk again until they stop watching it and then start watching it again. It's not fired constantly while a player is in the chunk.

 

 

Access the holder capability through the World and then use it to get the energy storage for the chunk. I created helper methods in CapabilityChunkEnergy to get the IChunkEnergy for a Chunk or World and ChunkPos.

Ok, thx. I've got just a little problem:

 

I'm sending a message to the player via ChunkWatchEvent.Watch to test if the code, but now I'm getting the following error inside of the message handler:

 

[22:59:21] [Client thread/FATAL]: Error executing task
java.util.concurrent.ExecutionException: java.lang.NullPointerException
	at java.util.concurrent.FutureTask.report(Unknown Source) ~[?:1.8.0_131]
	at java.util.concurrent.FutureTask.get(Unknown Source) ~[?:1.8.0_131]
	at net.minecraft.util.Util.runTask(Util.java:29) [Util.class:?]
	at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1108) [Minecraft.class:?]
	at net.minecraft.client.Minecraft.run(Minecraft.java:406) [Minecraft.class:?]
	at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_131]
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_131]
	at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
	at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_131]
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_131]
	at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_131]
	at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?]
	at GradleStart.main(GradleStart.java:26) [start/:?]
Caused by: java.lang.NullPointerException
	at minecraftplaye.justanotherenergy.common.network.msg.MessageChunkPollution$MessageChunkPollutionHandler.lambda$0(MessageChunkPollution.java:80) ~[MessageChunkPollution$MessageChunkPollutionHandler.class:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_131]
	at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_131]
	at net.minecraft.util.Util.runTask(Util.java:28) ~[Util.class:?]
	... 15 more

 

Here is the code:

    public static class MessageChunkPollutionHandler implements IMessageHandler<MessageChunkPollution, IMessage> {
        
        @Override
        public IMessage onMessage(MessageChunkPollution message, MessageContext ctx) {
            IThreadListener mainThread = Minecraft.getMinecraft();
            mainThread.addScheduledTask(() -> {
                final World world = Minecraft.getMinecraft().world;
                
                final IChunkPollutionHolder chunkPollutionHolder = CapabilityPollution.getChunkPollutionHolder(world);
                if(chunkPollutionHolder == null) return;
                
                final IChunkPollution chunkPollution = chunkPollutionHolder.getChunkPollution(new ChunkPos(message.chunkPosX, message.chunkPosZ));
                System.err.println("t: " + chunkPollution + " tt: " + chunkPollution == null); // output: false
                chunkPollution.setPollution(message.pollution); // Error occurs here
            });
            
            // No respond packet
            return null;
        }
    }

 

Developer of Primeval Forest.

Posted
10 hours ago, Bektor said:

I'm sending a message to the player via ChunkWatchEvent.Watch to test if the code, but now I'm getting the following error inside of the message handler:

 

The IChunkPollution for that chunk was null.

 

Are you creating a default IChunkPollution in ChunkEvent.Load when the Chunk doesn't already have one? This is required for client-side chunks, since ChunkDataEvent.Load only fires on the server.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted
9 hours ago, Choonster said:

 

The IChunkPollution for that chunk was null.

 

Are you creating a default IChunkPollution in ChunkEvent.Load when the Chunk doesn't already have one? This is required for client-side chunks, since ChunkDataEvent.Load only fires on the server.

Yes.

 

    @SubscribeEvent
    public void chunkLoad(ChunkEvent.Load event) {
        final World world = event.getWorld();
        final ChunkPos pos = event.getChunk().getChunkCoordIntPair();
        
        if(world == null || !world.hasCapability(CHUNK_POLLUTION_CAPABILITY, DEFAULT_FACING))
            return;
        final IChunkPollutionHolder chunkPollutionHolder = world.getCapability(CHUNK_POLLUTION_CAPABILITY, DEFAULT_FACING);
        if(chunkPollutionHolder == null) return;
        
        // don't create a IChunkPollution twice for a chunk
        if(chunkPollutionHolder.getChunkPollution(pos) != null) return;
        
        final IChunkPollution chunkPollution = new ChunkPollution(world, pos);
        chunkPollutionHolder.setChunkPollution(pos, chunkPollution);
    }

 

Developer of Primeval Forest.

Posted

Now that I look at your code closer, the IChunkPollution couldn't have been null on line 80 if it wasn't null on the previous line.

 

Set a breakpoint on that line and look at the values of the local variables when it's hit, which of them is null?

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted
15 minutes ago, Choonster said:

Now that I look at your code closer, the IChunkPollution couldn't have been null on line 80 if it wasn't null on the previous line.

 

Set a breakpoint on that line and look at the values of the local variables when it's hit, which of them is null?

Hm... It doesn't really bring me anywhere.. Setting the breakpoint at line 80 will just result into it that eclipse shows me that neither the world, nor the chunkPollutionHolder or the chunkPollution values are null.

Putting in this line of code results into this:

System.err.println(message.pollution); //output :0.0
System.err.println(message); // output: MessageChunkPollution@3fbdd7c8

Opening the chunkPollutionHolder shows me that the keySet and the values from the HashMap are null while the entrySet contains values.

Developer of Primeval Forest.

Posted (edited)
9 minutes ago, Bektor said:

Hm... It doesn't really bring me anywhere.. Setting the breakpoint at line 80 will just result into it that eclipse shows me that neither the world, nor the chunkPollutionHolder or the chunkPollution values are null.

Putting in this line of code results into this:


System.err.println(message.pollution); //output :0.0
System.err.println(message); // output: MessageChunkPollution@3fbdd7c8

 

That's strange. Can you reliably reproduce the NullPointerException, or has it only happened once?

 

Try removing the breakpoint on the line that throws the exception and replacing it with an exception breakpoint for NullPointerException. If the breakpoint is hit and the exception is being thrown on the same line as before, look at what's null.

 

Quote

Opening the chunkPollutionHolder shows me that the keySet and the values from the HashMap are null while the entrySet contains values.

 

That's normal, keySet and values are only created when they're first requested.

Edited by Choonster

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted
9 minutes ago, Choonster said:

 

That's strange. Can you reliably reproduce the NullPointerException, or has it only happened once?

 

Try removing the breakpoint on the line that throws the exception and replacing it with an exception breakpoint for NullPointerException. If the breakpoint is hit and the exception is being thrown on the same line as before, look at what's null.

 

 

That's normal, keySet and values are only created when they're first requested.

How can I create an exception breakpoint fpr NullPointerExceptions in eclipse?

Also the NPE still happens. I just removed the breakpoint, pressed resume and got it directly while I could click on resume before like a thousand times without anything happening.

I'm also not entirely sure under which situations it occurs, I just now it happens always when the world loads.

Developer of Primeval Forest.

Posted (edited)
52 minutes ago, Bektor said:

How can I create an exception breakpoint fpr NullPointerExceptions in eclipse?

 

Look at the documentation or use your search engine of choice.

 

If it's anything like IDEA, the Debug window should have a button that shows all breakpoints. Clicking this will bring up a window that also allows you to create new breakpoints.

Edited by Choonster

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted
10 minutes ago, Choonster said:

 

Look at the documentation or use your search engine of choice.

 

If it's anything like IDEA, the Debug window should have a button that shows all breakpoints. Clicking this will bring up a window that also allows you to create new breakpoints.

Hm, seems like eclipse has something like that, too. Thought I can't set the line of an exception breakpoint nor the class and for normal conditional breakpoints I have to write normal null checks like I would inside of the code, just inside of the breakpoint.

Developer of Primeval Forest.

Posted
Just now, Bektor said:

Hm, seems like eclipse has something like that, too. Thought I can't set the line of an exception breakpoint nor the class and for normal conditional breakpoints I have to write normal null checks like I would inside of the code, just inside of the breakpoint.

 

You shouldn't need to set the class/line or add any null checks, the breakpoint will be hit as soon as something throws a NullPointerException. Once your code throws the exception and hits the breakpoint, look at the debugger to see what's null.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted (edited)
15 minutes ago, Choonster said:

 

You shouldn't need to set the class/line or add any null checks, the breakpoint will be hit as soon as something throws a NullPointerException. Once your code throws the exception and hits the breakpoint, look at the debugger to see what's null.

Ok. Thougt now eclipse tells me always this: Source not found. Edit Source Lookup Path.

There it just gives me the option to select default and then it works. I click on resume and the same thing happens again.

 

EDIT: Ok, after literally pressing the Resume button like a 100 times I got to the point where my code starts... There it stopped on this line:

chunkPollution.setPollution(message.pollution);

The debug window shows me that chunkPollution is null while the console window showed me false just a few ms before for this statement: chunkPollution == null.

 

Console output:

Quote

false
[20:56:25] [Client thread/INFO] [STDERR]: [minecraftplaye.justanotherenergy.common.network.msg.MessageChunkPollution$MessageChunkPollutionHandler:lambda$0:80]: minecraftplaye.justanotherenergy.common.network.msg.MessageChunkPollution@334a373a
[20:56:25] [Server thread/WARN]: Can't keep up! Did the system time change, or is the server overloaded? Running 5453ms behind, skipping 109 tick(s)

.Code:

                final IChunkPollution chunkPollution = chunkPollutionHolder.getChunkPollution(new ChunkPos(message.chunkPosX, message.chunkPosZ));
                System.err.println("t: " + chunkPollution + " tt: " + chunkPollution == null);
                System.err.println(message);
                chunkPollution.setPollution(message.pollution);

Debug Window:

Quote

world = WorldClient (id=670)

chunkPollutionHolder = chunkPollutionHolder (id=674)

chunkPollution = null

 

Edited by Bektor

Developer of Primeval Forest.

Posted
1 minute ago, Bektor said:

Ok. Thougt now eclipse tells me always this: Source not found. Edit Source Lookup Path.

There it just gives me the option to select default and then it works. I click on resume and the same thing happens again.

 

It sounds like Eclipse is showing you NullPointerExceptions being thrown in external code that it doesn't have source code for.

 

Restrict the breakpoint to your message handler class by doing the following:

  • Show the Breakpoints view (Window > Show View > Other... > Debug > Breakpoints)
  • In the Breakpoints view, right click on the exception breakpoint and select Breakpoint Properties...
  • In the Properties window, select Filtering in the left column and then click Add Class...
  • Type in the name of your message handler class, select it in the search results and click OK.
  • Click OK in the Properties window.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted
10 minutes ago, Choonster said:

 

It sounds like Eclipse is showing you NullPointerExceptions being thrown in external code that it doesn't have source code for.

 

Restrict the breakpoint to your message handler class by doing the following:

  • Show the Breakpoints view (Window > Show View > Other... > Debug > Breakpoints)
  • In the Breakpoints view, right click on the exception breakpoint and select Breakpoint Properties...
  • In the Properties window, select Filtering in the left column and then click Add Class...
  • Type in the name of your message handler class, select it in the search results and click OK.
  • Click OK in the Properties window.

Oh, ok. Thx.

 

Console output:

Quote

[21:19:46] [Client thread/INFO] [STDERR]: [minecraftplaye.justanotherenergy.common.network.msg.MessageChunkPollution$MessageChunkPollutionHandler:lambda$0:80]: minecraftplaye.justanotherenergy.common.network.msg.MessageChunkPollution@59843821
false

Code:

 

                final IChunkPollution chunkPollution = chunkPollutionHolder.getChunkPollution(new ChunkPos(message.chunkPosX, message.chunkPosZ));
                System.err.println("t: " + chunkPollution + " tt: " + chunkPollution == null);
                System.err.println(message);
                chunkPollution.setPollution(message.pollution);

Debug Window:

Quote

world = WorldClient (id=670)

chunkPollutionHolder = chunkPollutionHolder (id=674)

chunkPollution = null

Developer of Primeval Forest.

Posted

That output doesn't appear to match your code. Where did the "false" message come from? What did the first System.err.println call output?

 

It appears that chunkPollution is indeed null. Is the ChunkEvent.Load handler definitely being called? Was it called for the chunk that produces this error?

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted
Just now, Choonster said:

That output doesn't appear to match your code. Where did the "false" message come from? What did the first System.err.println call output?

 

It appears that chunkPollution is indeed null. Is the ChunkEvent.Load handler definitely being called? Was it called for the chunk that produces this error?

It should have been called. I registered the entire class as a event handler using MinecraftForge.EVENT_BUS.register(new CapabilityPollution()); in FMLInitializationEvent within the ServerProxy.

And all events have the @SubscribeEvent annotation on them, so they should be recognized and called.

 

Just change a bit of the code to get more information out of it:

As I am no longer using System.err.println but instead System.out.println the order of the output matches now also the order of the code. ;)

 

Quote

chunkPollution: null
 Position: -1 | -1
Player Position: 10 | 12

 

                final IChunkPollution chunkPollution = chunkPollutionHolder.getChunkPollution(new ChunkPos(message.chunkPosX, message.chunkPosZ));
                System.out.println("chunkPollution: " + chunkPollution);
                System.out.println("Position: " + message.chunkPosX + " | " + message.chunkPosZ);
                System.out.println("Player Position: " + ((int)(Minecraft.getMinecraft().player.posX) >> 4) + " | " + ((int)(Minecraft.getMinecraft().player.posZ) >> 4));
                chunkPollution.setPollution(message.pollution);

 

So it seems like the error occurs inside of a chunk in which the player currently is not.

Also this is the data from the map from my chunkPollutionHolder.

Quote

{[-1, 1]=ChunkPollution@2f319ca3, 
[-1, 6]=ChunkPollution@8a2e3b6, 
[-1, 3]=ChunkPollution@2942e7cb, 
[-1, 2]=ChunkPollution@2fa015bc, 
[-1, 5]=ChunkPollution@1e400e08, 
[-1, 7]=ChunkPollution@1177e2c4, 
[-1, 10]=ChunkPollution@36a8ef12, 
[-1, 8]=ChunkPollution@29881522, 
[-1, 9]=ChunkPollution@37a66e55, 
[-1, 4]=ChunkPollution@3ab59822}

As of the chunk which is causing the problem isn't in the list I guess it wasn't called at the point where the client player added it to it's watch list.

 

 

Developer of Primeval Forest.

Posted (edited)

If I am correct and the problem is caused by it that data was sent to the client for which the chunk events haven't run yet, how can I prevent this from occuring?

 

EDIT: fixed. Just implemented an extra null check for IChunkPollution. I hope nothing else get's messed up because of this.

Seems also that other code parts didn't had an npe because of instanceof checks which also check for null.

Edited by Bektor
solved

Developer of Primeval Forest.

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.