Jump to content

Recommended Posts

Posted

 

I've read the docs and coded with reference to the existing mod code, but there are many things I don't understand. What should I put in with () of sendToClient of DepressionModPacketHandler? Also, I don't know what to do with encode, decode, and handle of PlayerMentalCapabilityMessage.

 

public class DepressionModPacketHandler {
	private static final String PROTOCOL_VERSION = "1";  //プロトコルのバージョンを宣言
	public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(  //INSTANCEに=の右側以下をぶち込む
			new ResourceLocation(DepressionMod.MOD_ID, "main"),
			() -> PROTOCOL_VERSION,  //プロトコルのバージョンをぶち込む
			PROTOCOL_VERSION::equals,  //クライアントのバージョンとPROTOCOL_VERSIONを比較?
			PROTOCOL_VERSION::equals);  //サーバーのバージョンとPROTOCOL_VERSIONを比較?

	//パケットの登録
	public static void packetRegister() {
		INSTANCE.registerMessage(
				0,  //パケットの識別子
				PlayerMentalCapabilityMessage.class,  //実際のパケットクラス
				PlayerMentalCapabilityMessage::encode,  //エンコード
				PlayerMentalCapabilityMessage::decode,  //デコード
				PlayerMentalCapabilityMessage::handle);  //メッセージ自体の処理
	}

	public static void sendToClient(Object message, PlayerEntity player) {
		INSTANCE.send(PacketDistributor.PLAYER.with(null), new PlayerMentalCapabilityMessage());
	}
}
package depressionmod.network;

import java.util.function.Supplier;

import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;

public class PlayerMentalCapabilityMessage {
	public static void encode(PlayerMentalCapabilityMessage message, PacketBuffer buf) {

	}

	public static PlayerMentalCapabilityMessage decode(PacketBuffer buf) {
		return null;

	}

	public static void handle(PlayerMentalCapabilityMessage msg, Supplier<NetworkEvent.Context> ctx) {

	}
}

 

Posted

In other words, I understand that with () should contain mental, which is the value I want to reflect in the HUD, but I don't know how to get the value of that capability.

Posted
INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), new PlayerMentalCapabilityMessage());

When I searched for the code of the existing mod, I found the above sentence. Even if I change this ServerPlayerEntity to PlayerEntity, an error is displayed.

Posted
public class PlayerMentalCapabilityMessage {
	private final int currentMental;

	public PlayerMentalCapabilityMessage(int currentMental) {
		this.currentMental = currentMental;
	}

	public static void encode(PlayerMentalCapabilityMessage message, PacketBuffer buf) {
		buf.writeInt(message.currentMental);
	}

	public static PlayerMentalCapabilityMessage decode(PacketBuffer buf) {
		int currentMental = buf.readInt();
		return new PlayerMentalCapabilityMessage(currentMental);

	}

	public static void handle(PlayerMentalCapabilityMessage msg, Supplier<NetworkEvent.Context> ctx) {
		//Player player = Minecraft.pla
		ctx.get().enqueueWork(() -> {
			PlayerMental playerMental = (PlayerMental) PlayerEntity.getCapability(PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY);
		});
	}
}

 

I wrote the code with reference to the existing mod, but I still don't know what to do with the contents of the handle. I'm sorry to have taken the trouble, but if possible, I would like a sample code and its explanation.

Posted

It seems like you are syncing an int to the client?

You can use dist executor to make sure you are on the right side and get the capability from the client player (using Minecraft.getInstance().player), then you can set the value got from the packet (msg.currentMental).

Also make sure you have packet set handled Context.setPacketHandled()

Posted
public class PlayerMentalCapabilityMessage {
	ClientPlayerEntity player = Minecraft.getInstance().player;
	LazyOptional<PlayerMentalInterface> playermentalinterface = player.getCapability(PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY);
	int currentMental = ((PlayerMentalInterface) playermentalinterface).getMental();

	public PlayerMentalCapabilityMessage(int currentMental) {
		this.currentMental = currentMental;
	}

	public static void encode(PlayerMentalCapabilityMessage message, PacketBuffer buf) {
		buf.writeInt(message.currentMental);
	}

	public static PlayerMentalCapabilityMessage decode(PacketBuffer buf) {
		int currentMental = buf.readInt();
		return new PlayerMentalCapabilityMessage(currentMental);

	}

	public static void handle(PlayerMentalCapabilityMessage msg, Supplier<NetworkEvent.Context> ctx) {
		ctx.get().enqueueWork(() -> {
			
		});
	}
}

Is it like this? I'm still not sure about Context.setPacketHandled () so please tell me more.

Posted (edited)

Handle is called when the client has received the packet, so there should be where you sync the data (what you've done in the previous post is correct), which you should get the client player and its capability to sync in here.

Also: 

56 minutes ago, poopoodice said:

You can use dist executor to make sure you are on the right side

You can get the context from the supplier (given in the second parameter of handle(...), then call Context#setPacketHandled)

Edited by poopoodice
Posted
	public static void handle(PlayerMentalCapabilityMessage msg, Supplier<NetworkEvent.Context> ctx) {
		ctx.get().enqueueWork(() -> {

			

		});
		ctx.get().setPacketHandled(true);
	}

Is this all right?

public static void handle(MyMessage msg, Supplier<NetworkEvent.Context> ctx) {
    ctx.get().enqueueWork(() -> {
        // Work that needs to be threadsafe (most work)
        EntityPlayerMP sender = ctx.get().getSender(); // the client that sent this packet
        // do stuff
    });
    ctx.get().setPacketHandled(true);
}

This is what the forge docs say, but if I'm right, EntityPlayerMP sender = ctx.get (). GetSender (); is for sending from client to server. I don't know how to send from server to client instead.

public class MentalOverlayHander {
	public static final ResourceLocation MENTALICON = new ResourceLocation("depressionmod:textures/gui/overlay.png");

	private final Minecraft mc = Minecraft.getInstance();
	public int _currentMental;

	@SubscribeEvent
	public void onPreRenderOverlay(RenderGameOverlayEvent.Post event) {
		if (event.getType() == ElementType.ALL && mc.playerController.gameIsSurvivalOrAdventure()) {
			int scaledWidth = this.mc.getMainWindow().getScaledWidth();
			int scaledHeight = this.mc.getMainWindow().getScaledHeight();
			int left_height = ForgeIngameGui.left_height;
			int left = scaledWidth / 2 - 91;
			int top = scaledHeight - left_height;
			int level = _currentMental;

			RenderSystem.enableBlend();
			RenderSystem.enableAlphaTest();
			RenderSystem.color4f(1F, 1F, 1F, 1F);
			mc.getTextureManager().bindTexture(MENTALICON);
			for (int i = 0; i < 10; ++i) {  //iが10未満のとき繰り返す。iは繰り返しごとに1増える。
				int idx = i * 2 + 1;
				if (idx < level) {   //iがMPより小さいとき普通の薬を描画。
					//mc.getTextureManager().bindTexture(MENTALICON);
					mc.ingameGUI.blit(left, top, 0, 0, 9, 9);
				}
				else if (idx == level) {  //iがMPと同じとき半分の薬を描画。
					//mc.getTextureManager().bindTexture(MENTALICON);
					mc.ingameGUI.blit(left, top, 9, 0, 9, 9);
				}
				else if (idx > level) {  //iがMPより大きいとき黒の薬を描画。
					//mc.getTextureManager().bindTexture(MENTALICON);
					mc.ingameGUI.blit(left, top, 18, 0, 9, 9);
				}
				left += 8;  //アイコンを描画する位置を右に一つ分ずらす
				
			}
			RenderSystem.disableBlend();
			mc.getTextureManager().bindTexture(AbstractGui.GUI_ICONS_LOCATION);
			
	        }
	}
}

I want to put the currentMental value of PlayerMentalCapabilityMessage in _currentMental of MentalOverlayHander.

Posted (edited)

That's right.

That me briefly explain the situation here:

You want to sync the mental value of the player on server to client, and you had sent a packet that contains the value, in order to use it and render images on the screen.
To get the value when rendering the screen, you are going to access the capability of the client player, therefore you need to assign the value from the packet to the client player's capability.

 

So: (make sure you do this on client using dist executor!)

MyCap cap = Minecraft.getInstance().player.getCapability(....);

cap.setMental(valuefromserver);

 

where cap is the client player' capability, and valuefromserver is the mental value got from the server player's capability that you want to assign(Sync) to the client.

 

Then you can use the same way above to access the value stored in the capability of the client player to render the images.

 

Also make sure you only send the packet when there's data change.

Edited by poopoodice
Posted (edited)

I'm sorry, I still don't have enough knowledge and understanding about Dist Executor. I tried searching, but I created a clientproxy class and what happens when the data is changed there (in this case,
MyCap cap = Minecraft.getInstance (). player.getCapability (....);

cap.setMental (valuefromserver);
Is it correct to recognize that it executes this code?

 

nothing. I may have found the appropriate sample code. With that as a reference, I will think for a moment.

Edited by Zemelua
Posted
public class PlayerMentalCapabilityMessage {
	ClientPlayerEntity player = Minecraft.getInstance().player;  //getInstance().playerをplayerにぶち込む
	LazyOptional<PlayerMentalInterface> playerMentalInterface = player.getCapability(PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY);
		//playerからキャパビリティを取得してplayerMentalInterfaceにぶち込む
	int currentMental = ((PlayerMentalInterface) playerMentalInterface).getMental();  //playerMentalInterfaceからmentalの値を取得してcurrentMentalにぶち込む

	public PlayerMentalCapabilityMessage(int currentMental) {
		this.currentMental = currentMental;
	}

	public static void encode(PlayerMentalCapabilityMessage message, PacketBuffer buf) {
		buf.writeInt(message.currentMental);
	}

	public static PlayerMentalCapabilityMessage decode(PacketBuffer buf) {
		int currentMental = buf.readInt();
		return new PlayerMentalCapabilityMessage(currentMental);

	}

	public static void handle(PlayerMentalCapabilityMessage message, Supplier<NetworkEvent.Context> ctx) {
		ctx.get().enqueueWork(() -> {
			DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> Handle.handleClient(message.currentMental));
		});
		ctx.get().setPacketHandled(true);
	}

	public static class Handle {
		public static DistExecutor.SafeRunnable handleClient(int currentMental) {
			return new DistExecutor.SafeRunnable() {
				@Override
				public void run() {
					LazyOptional<PlayerMentalInterface> cap = Minecraft.getInstance().player.getCapability(PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY);
					((PlayerMentalInterface) cap).setMental(currentMental);
					//MinecraftForge.EVENT_BUS.post(new DietModEvents.UpdatePlayerSizeEvent((PlayerEntity) player));
					/*Entity player = Minecraft.getInstance().world.getEntityByID(playerEntityID);
					if (!(player instanceof PlayerEntity)) return;
					player.getCapability(ScaleProvider.SCALE_CAP).orElseThrow(IllegalArgumentException::new).setScale(scale);
					MinecraftForge.EVENT_BUS.post(new DietModEvents.UpdatePlayerSizeEvent((PlayerEntity) player));
					*/
				}
			};
		}
	}
}

I wrote the code with reference to https://forums.minecraftforge.net/topic/89515-solved1161client-works-but-server-crashes-at-packet-handler, but what role does safeRunWhenOn have? I don't really understand it, so please let me know.

Posted

If you look into Minecraft.java, you will notice that it has an annotation:

@OnlyIn(Dist.CLIENT)

and according to forge doc:

Annotating a method or field with the @OnlyIn(Dist) annotation indicates to the loader that the respective member should be completely stripped out of the definition not on the specified physical side. Usually, these are only seen when browsing through the decompiled Minecraft code, indicating methods that the Mojang obfuscator stripped out. There is little to no reason for using this annotation directly. Only use it if you are overriding a vanilla method that already has @OnlyIn defined. In most other cases where you need to dispatch behavior based on physical sides, use DistExecutor or a check on FMLEnvironment.dist instead.

 

In other word, Minecraft.java does not exist on server side! You know what will happen when you have an non-existence reference.

Posted
((PlayerMentalInterface) cap).setMental(currentMental);

This is not right, you need to get the capability out of the lazy optional (use

orElseThrow

), not casting it.

You might find this thread helpful: 

 

 

Posted
    public static void handle(PlayerMentalCapabilityMessage message, Supplier<NetworkEvent.Context> ctx) {
        ctx.get().enqueueWork(() -> {
            DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> Handle.handleClient(message.currentMental));
        });
        ctx.get().setPacketHandled(true);
    }

    public static class Handle {
        public static DistExecutor.SafeRunnable handleClient(int currentMental) {
            return new DistExecutor.SafeRunnable() {
                @Override
                public void run() {
                    LazyOptional<PlayerMentalInterface> cap = Minecraft.getInstance().player.getCapability(PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY);
                    cap.orElseThrow(IllegalArgumentException::new).setMental(currentMental);
                }
            };
        }
    }
}

Is this right?

Posted

Thanks to everyone, I was able to achieve what I wanted to do. Thank you very much. I'm not good at English, so it's often difficult to understand even after reading the tutorial, but actually speaking in text here makes it somewhat easier to understand.

public class DepressionModPacketHandler {
	private static final String PROTOCOL_VERSION = "1";  //プロトコルのバージョンを宣言
	public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(  //INSTANCEに=の右側以下をぶち込む
			new ResourceLocation(DepressionMod.MOD_ID, "main"),
			() -> PROTOCOL_VERSION,  //プロトコルのバージョンをぶち込む
			PROTOCOL_VERSION::equals,  //クライアントのバージョンとPROTOCOL_VERSIONを比較?
			PROTOCOL_VERSION::equals);  //サーバーのバージョンとPROTOCOL_VERSIONを比較?

	//パケットの登録
	public static void packetRegister() {
		INSTANCE.registerMessage(
				0,  //パケットの識別子
				PlayerMentalCapabilityMessage.class,  //実際のパケットクラス
				PlayerMentalCapabilityMessage::encode,  //エンコード
				PlayerMentalCapabilityMessage::decode,  //デコード
				PlayerMentalCapabilityMessage::handle);  //メッセージ自体の処理
	}

	public static void sendToClient(Object message, PlayerEntity player) {

		INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), message);
	}
}
public class PlayerMentalCapabilityMessage {
	ClientPlayerEntity player = Minecraft.getInstance().player;  //getInstance().playerをplayerにぶち込む
	LazyOptional<PlayerMentalInterface> playerMentalInterface = player.getCapability(PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY);
		//playerからキャパビリティを取得してplayerMentalInterfaceにぶち込む
	int currentMental = ((PlayerMentalInterface) playerMentalInterface).getMental();  //playerMentalInterfaceからmentalの値を取得してcurrentMentalにぶち込む

	public PlayerMentalCapabilityMessage(int currentMental) {
		this.currentMental = currentMental;
	}

	public static void encode(PlayerMentalCapabilityMessage message, PacketBuffer buf) {
		buf.writeInt(message.currentMental);
	}

	public static PlayerMentalCapabilityMessage decode(PacketBuffer buf) {
		int currentMental = buf.readInt();
		return new PlayerMentalCapabilityMessage(currentMental);

	}

	public static void handle(PlayerMentalCapabilityMessage message, Supplier<NetworkEvent.Context> ctx) {
		ctx.get().enqueueWork(() -> {
			DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> Handle.handleClient(message.currentMental));
		});
		ctx.get().setPacketHandled(true);
	}

	public static class Handle {
		public static DistExecutor.SafeRunnable handleClient(int currentMental) {
			return new DistExecutor.SafeRunnable() {
				@Override
				public void run() {
					LazyOptional<PlayerMentalInterface> cap = Minecraft.getInstance().player.getCapability(PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY);
					cap.orElseThrow(IllegalArgumentException::new).setMental(currentMental);
				}
			};
		}
	}
}
public class MentalOverlayHander {
	public static final ResourceLocation MENTALICON = new ResourceLocation("depressionmod:textures/gui/overlay.png");

	private final Minecraft mc = Minecraft.getInstance();

	@SubscribeEvent
	public void onPreRenderOverlay(RenderGameOverlayEvent.Post event) {
		if (event.getType() == ElementType.ALL && mc.playerController.gameIsSurvivalOrAdventure()) {
			int scaledWidth = this.mc.getMainWindow().getScaledWidth();
			int scaledHeight = this.mc.getMainWindow().getScaledHeight();
			int left_height = ForgeIngameGui.left_height;
			int left = scaledWidth / 2 - 91;
			int top = scaledHeight - left_height;

			LazyOptional<PlayerMentalInterface> cap = Minecraft.getInstance().player.getCapability(PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY);
			int level =cap.orElseThrow(IllegalArgumentException::new).getMental();
			//int level = currentMental; //((PlayerMentalInterface) PlayerMentalCapabilityRegistry.PLAYER_MENTAL_CAPABILITY).getMental();

			RenderSystem.enableBlend();
			RenderSystem.enableAlphaTest();
			RenderSystem.color4f(1F, 1F, 1F, 1F);
			mc.getTextureManager().bindTexture(MENTALICON);
			for (int i = 0; i < 10; ++i) {  //iが10未満のとき繰り返す。iは繰り返しごとに1増える。
				int idx = i * 2 + 1;
				if (idx < level) {   //iがMPより小さいとき普通の薬を描画。
					//mc.getTextureManager().bindTexture(MENTALICON);
					mc.ingameGUI.blit(left, top, 0, 0, 9, 9);
				}
				else if (idx == level) {  //iがMPと同じとき半分の薬を描画。
					//mc.getTextureManager().bindTexture(MENTALICON);
					mc.ingameGUI.blit(left, top, 9, 0, 9, 9);
				}
				else if (idx > level) {  //iがMPより大きいとき黒の薬を描画。
					//mc.getTextureManager().bindTexture(MENTALICON);
					mc.ingameGUI.blit(left, top, 18, 0, 9, 9);
				}
				left += 8;  //アイコンを描画する位置を右に一つ分ずらす

			}
			RenderSystem.disableBlend();
			mc.getTextureManager().bindTexture(AbstractGui.GUI_ICONS_LOCATION);

	        }
	}
}

151265158_(31).thumb.png.fc0d935736ed9219d5730256253ddb70.png

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



×
×
  • Create New...

Important Information

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