Jump to content

Recommended Posts

Posted

Hey,

in my gui when button is activated it send packet to server.

By data send to server it adds task to mob tasks list.

In packet sender class I can see that size of the list is growing up correctly, but when I try to get data from my list by entity class system tells that list size is 0.

I will post some code if it helps.

Posted

when I try to get data from my list by entity class system tells that list size is 0.

I will post some code if it helps.

 

I don't understand this part.  Post this code

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

Ok, I will post all code for better explanation.

 

In method actionPerformed().

ModBetterWorld.packets.sendToServer(new GuiRequestPacketAddOrder(this.villager.getEntityId(), guiButton.id));

 

 

That code adds tasks to list, entity is set by id system and task by my other list with possible tasks to add.

In that part of code, system prints that my taskEntries(I need to change the name) is growing on each button click so system adds tasks to list.

@Override
public IMessage onMessage(GuiRequestPacketAddOrder message, MessageContext ctx)
{
	EntityPlayer player = ctx.getServerHandler().playerEntity;
	World world = player.worldObj;
	EntityBetterVillager entity = (EntityBetterVillager) world.getEntityByID(message.entityID);

	entity.order.addTask((EntityAIBaseOrder) entity.possibleOrders.get(message.buttonID - 3));	
	System.out.println(entity.order.taskEntries.size());
	return null;
} 

 

Code for adding tasks to list using method.

    public List taskEntries = new ArrayList();

    public void addTask(EntityAIBaseOrder p_75776_2_)
    {
        this.taskEntries.add(p_75776_2_);
    }

 

That code is in initGui(). It should return the same size as in packet class but it doesnt.

System.out.println(this.villager.order.taskEntries.size());

 

 

Posted

Ok but are any way to get tasks on clinent side?

I need it to my gui, because clicling another buttons will remove tasks.

 

Send a packet to the server, the GUI is only a presentation layer nothing except drawing should be computed on the Client.

 

MC Client = Presentation Layer

Packets = Transport Layer

MC Server = Logic/Business Layer

 

If you follow that pattern everything should work, clicking a button should just send a packet and the server does everything.

I require Java, both the coffee and the code :)

Posted

Using system.out.print I have noticed that list of tasks is null only in one side.

So the size on client and server isnt synchronized.

Only the server side list is changing. I dont know more but I think that I need to get my list from server not from client as I have in gui.

Posted

You will have to make response Server->Client packet.

 

Simply send packet to player that is viewing GUI whenever task-list changes. You can put response in onMessage or directly into entity class (make wrapper for addTask that will take addTaskWrapped(EntityAIBaseOrder task, EntityPlayer player) and send update packet to player from arguments). You will ofc have to also put packet-update in other places. I'd suggest making refresh button on client-side which would request tasks from server.

1.7.10 is no longer supported by forge, you are on your own.

Posted

I think I found a solution.

Few weeks earlier I have similar problem with inventory.

I will try to refresh(send packet from server to client) each time my gui changes

Now I need to make new packet class and I will post later if I managed to do that.

Posted

Is any good way to write and read an object like ArrayList??

I can try to make an id for each order and write only int and than read that id and set a order maching to that id.

I dont know is my way quite good so I am waiting for your sugestions.

Posted

I know the same is with ItemStack, it can be sended as primitives.

But my orders arent made in that way. I think the easiest will be writing the order id and other settings and that reading it and combining into order object. I am not sure will it work.

Posted

"But my orders arent made in that way."

 

There is no other way. Evrything IS made of bytes. If it exists, you can write it to buffer.

 

Maybe share how are your orders made?

1.7.10 is no longer supported by forge, you are on your own.

Posted

General order class:

public abstract class EntityAIBaseOrder
{
private int id;

public EntityAIBaseOrder(int par)
{
	this.id = par;
}

public int getId()
{
	return id;
}

    //Zwraca czy rozkaz powinien zostac wykonany, cos co od razu dziala to true, jesli musi byc cos spelnione to dac warunki
    public abstract boolean shouldExecute();

    //To jest wykonywane tylko raz podczas zaczecia polecenia, tutaj powinny byc cele poczatkowe
    public void startExecuting() {}

    //Wykonywane, gdy zadanie jest przerwane.
    public void resetTask() {}

    //Wykowywane jest za kazdym tickiem systemu
    public void updateTask() {}
    
    //Zwraca czy rozkaz zostal rozpoczety
    public abstract boolean hasStarted();
    
    //Zwraca czy cele rozkazu zostaly osiagniete
    public abstract boolean isDone();
}

 

My exaple of order to look does the system work.

public class EntityAIStayHere extends EntityAIBaseOrder
{
    private EntityBetterVillager villager;
    private boolean isStarted;
    private boolean isDone;
    
    public EntityAIStayHere(EntityBetterVillager villager, int par)
    {
    	super(par);
    	this.villager = villager;
    }

    public boolean shouldExecute()
    {
    	return true;
    }

    public void startExecuting()
    {
    	this.isStarted = true;
    	this.villager.getNavigator().tryMoveToXYZ(this.villager.posX, this.villager.posY, this.villager.posZ, 0.6D);
    }   

    public void resetTask()
    {
    	this.isStarted = false;
    	this.villager.getNavigator().clearPathEntity();
    }

    public void updateTask()
    {
    	
    }

@Override
public boolean hasStarted()
{
	return isStarted;
}

@Override
public boolean isDone()
{
	return false;
}

That order might not work, but its set to not be removed.

 

Tell me how do you want to get from it primitives types without using id or sth like this.

 

Posted

Are those tasks shared between server-client? (both client and server has every task class and can do whetever he wants with it)

In that case - yeah, use ID for each task and send only packet with id. I suggest having HashMap with all registered tasks (id, task) and make method getTaskById();

 

And that'll be perfectly fine. I was thinking that you are making custom tasks inside config and want to send them to client.

In that case you would need a well-done constructor system and use some nice checksums and data holders, but that's not the case here.

 

I btw. siemka :) Coraz więcej Polaków tu widzę.

1.7.10 is no longer supported by forge, you are on your own.

Posted

Hm, I made class for sending packets form server to client but still both sides arent the same.

Where I should call my method to send packets?

Right now its in general order class and I call it in entity class each second.

Posted

You need to send packet everytime something is changed (added/removed) in list to keep it synced.

1.7.10 is no longer supported by forge, you are on your own.

Posted

Done, sth has changed. Now I get errors.

io.netty.handler.codec.EncoderException: java.lang.ClassCastException: java.util.ArrayList cannot be cast to BetterWorld.ai.EntityAIBaseOrder

 

this.taskEntries() is an arraylist with stored EntityAIBaseOrder objects.

    public void syncOrders()
    {    	
    	ModBetterWorld.packets.sendToAll(new GuiRequestPacketSendOrders(this.villager.getEntityId(), this.taskEntries));
    }

 

There objects should be copied and stored in List orders.

private List orders = new ArrayList();
public GuiRequestPacketSendOrders(int id, List orders)
{
	this.entityId = id;
	this.orders = orders;
}

 

And here I get and error. The list should store correct object but it doesnt and gets error.

buffer.writeInt(((EntityAIBaseOrder) this.orders).getId());

Posted

Done, sth has changed. Now I get errors.

io.netty.handler.codec.EncoderException: java.lang.ClassCastException: java.util.ArrayList cannot be cast to BetterWorld.ai.EntityAIBaseOrder

 

this.taskEntries() is an arraylist with stored EntityAIBaseOrder objects.

    public void syncOrders()
    {    	
    	ModBetterWorld.packets.sendToAll(new GuiRequestPacketSendOrders(this.villager.getEntityId(), this.taskEntries));
    }

 

There objects should be copied and stored in List orders.

private List orders = new ArrayList();
public GuiRequestPacketSendOrders(int id, List orders)
{
	this.entityId = id;
	this.orders = orders;
}

 

And here I get and error. The list should store correct object but it doesnt and gets error.

buffer.writeInt(((EntityAIBaseOrder) this.orders).getId());

 

Does "EntityAIBaseOrder" extend ArrayList? Because if not you cannot cast the object EntityAIBaseOrder to an ArrayList.

I require Java, both the coffee and the code :)

Posted

Notfing has changed. Still the same error.

 

	for (int i = 0; i < this.orders.size(); i++)
	{
		System.out.println(this.orders.size());
		buffer.writeInt(((EntityAIBaseOrder) this.orders.get(i)).getId());
	}

Ups, I forgot to add .get(i)

I wanted to get an object from list and get grom it and id.

Adding it solved the error.

Posted

Again very strange error.

Below are two methods. In first this.orders isnt null, but in second is null.

When I put print method in first met. it shows size, in second met. I get an error.

Why it happens when it should not??

public void toBytes(ByteBuf buffer)
{
	buffer.writeInt(this.entityId);
	System.out.println(this.orders.size());
	for (int i = 0; i < this.orders.size(); i++)
	{			
		buffer.writeInt(((EntityAIBaseOrder) this.orders.get(i)).getId());
	}
}
  
public void fromBytes(ByteBuf buffer)
{
	this.entityId = buffer.readInt();

	if(this.orders != null)
	{
		for (int j = 0; j < this.orders.size(); j++)
		{
			this.orders.add(j, this.orderSystem.getOrderById(buffer.readInt())); 
		}
	}
}

Posted

Let's say:

- Server has 10 orders on given entity

- Client has none (need to be updated)

 

What happens in your code:

Server:

1. You write int (entityID)

2. You write 10x ints (order Id's)

Client:

1. You read 1st int (entityID)

2. Checking if orders aren't null (they most likely are, if you didn't init them)

3. You attempt to read as many int's fromreceived message as your client-side order list, which at that very momeny is EQUAL TO 0.

4. Nothing is read, because loop has (j = 0) < (size = 0).

 

What you need:

After writing entityID, write one more int - number of id's sent.

Read that int and put it as j < size in reader.

 

Overall note:

If client has 5 orders and server has 10, client will receive 10 orders, no matter if you alredy have them on client. So most likely you will end up with duplicates. Fix: Send all Id's when one is changed and on client-side clear order list and set to received one OR send only lacking orders (harder, more efficient).

1.7.10 is no longer supported by forge, you are on your own.

Posted

Well, obviously :o

toBytes writed data to byte stream (buffer) and fromBytes reads it. Sender writes, receiver reads.

1.7.10 is no longer supported by forge, you are on your own.

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

    • So me and a couple of friends are playing with a shitpost mod pack and one of the mods in the pack is corail tombstone and for some reason there is a problem with it, where on death to fire the player will get kicked out of the server and the tombstone will not spawn basically deleting an entire inventory, it doesn't matter what type of fire it is, whether it's from vanilla fire/lava, or from modded fire like ice&fire/lycanites and it's common enough to where everyone on the server has experienced at least once or twice and it doesn't give any crash log. a solution to this would be much appreciated thank you!
    • It is 1.12.2 - I have no idea if there is a 1.12 pack
    • Okay, but does the modpack works with 1.12 or just with 1.12.2, because I need the Forge client specifically for Minecraft 1.12, not 1.12.2
    • 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() ); } }  
  • Topics

×
×
  • Create New...

Important Information

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