提供: Minecraft Modding Wiki
細 |
(クラス名が明らかにスペルミスだったので修正) |
||
(2人の利用者による、間の10版が非表示) | |||
1行目: | 1行目: | ||
{{前提MOD|reqmod="Minecraft Forge Universal 10.12.1.1090~"}} | {{前提MOD|reqmod="Minecraft Forge Universal 10.12.1.1090~"}} | ||
− | |||
{{ チュートリアル難易度 | difficulty=1|clear=none}} | {{ チュートリアル難易度 | difficulty=1|clear=none}} | ||
− | {{ チュートリアルカテゴリー | | + | {{ チュートリアルカテゴリー |difficulty=1|type=Player}} |
{{stb}} | {{stb}} | ||
==プレイヤーへのカスタムデータの追加== | ==プレイヤーへのカスタムデータの追加== | ||
18行目: | 17行目: | ||
import cpw.mods.fml.common.Mod.EventHandler; | import cpw.mods.fml.common.Mod.EventHandler; | ||
import cpw.mods.fml.common.event.FMLInitializationEvent; | import cpw.mods.fml.common.event.FMLInitializationEvent; | ||
− | import cpw.mods.fml.common.event. | + | import cpw.mods.fml.common.event.FMLPreInitializationEvent; |
import cpw.mods.fml.common.eventhandler.SubscribeEvent; | import cpw.mods.fml.common.eventhandler.SubscribeEvent; | ||
import cpw.mods.fml.common.gameevent.PlayerEvent; | import cpw.mods.fml.common.gameevent.PlayerEvent; | ||
35行目: | 34行目: | ||
@Mod(modid = "SampleMod", name = "SampleMod", version = "1.0", dependencies = "required-after:Forge@[10.12.1.1090,)", useMetadata = true) | @Mod(modid = "SampleMod", name = "SampleMod", version = "1.0", dependencies = "required-after:Forge@[10.12.1.1090,)", useMetadata = true) | ||
public class SampleMod { | public class SampleMod { | ||
− | + | @SidedProxy(clientSide = "sampleMod.ClientProxy", serverSide = "sampleMod.CommonProxy") | |
− | + | public static CommonProxy proxy; | |
− | |||
@EventHandler | @EventHandler | ||
− | public void preInit( | + | public void preInit(FMLPreInitializationEvent event) { |
//Messageの登録呼び出し | //Messageの登録呼び出し | ||
PacketHandler.init(); | PacketHandler.init(); | ||
46行目: | 44行目: | ||
@EventHandler | @EventHandler | ||
public void init(FMLInitializationEvent event) { | public void init(FMLInitializationEvent event) { | ||
+ | //二箇所に登録するので、先にインスタンスを生成しておく。 | ||
+ | SampleEntityPropertiesEventHandler sampleEntityPropertiesEventHandler = new SampleEntityPropertiesEventHandler(); | ||
//Forge Eventの登録。EntityEvent.EntityConstructingとLivingDeathEventとEntityJoinWorldEvent | //Forge Eventの登録。EntityEvent.EntityConstructingとLivingDeathEventとEntityJoinWorldEvent | ||
− | MinecraftForge.EVENT_BUS.register( | + | MinecraftForge.EVENT_BUS.register(sampleEntityPropertiesEventHandler); |
− | //FML | + | //FML Eventの登録。PlayerRespawnEvent |
− | FMLCommonHandler.instance().bus().register( | + | FMLCommonHandler.instance().bus().register(sampleEntityPropertiesEventHandler); |
} | } | ||
+ | } | ||
+ | </source> | ||
+ | ===SampleEntityPropertiesEventHandlerクラス=== | ||
+ | <source lang = "java"> | ||
+ | package sampleMod; | ||
+ | |||
+ | import cpw.mods.fml.common.eventhandler.SubscribeEvent; | ||
+ | import cpw.mods.fml.common.gameevent.PlayerEvent; | ||
+ | import net.minecraft.entity.player.EntityPlayer; | ||
+ | import net.minecraft.entity.player.EntityPlayerMP; | ||
+ | import net.minecraft.nbt.NBTTagCompound; | ||
+ | import net.minecraftforge.common.IExtendedEntityProperties; | ||
+ | import net.minecraftforge.event.entity.EntityEvent; | ||
+ | import net.minecraftforge.event.entity.EntityJoinWorldEvent; | ||
+ | |||
+ | public class SampleEntityPropertiesEventHandler { | ||
+ | |||
+ | /*IExtendedEntityPropertiesを登録する処理を呼び出す*/ | ||
@SubscribeEvent | @SubscribeEvent | ||
− | |||
public void onEntityConstructing(EntityEvent.EntityConstructing event) { | public void onEntityConstructing(EntityEvent.EntityConstructing event) { | ||
if (event.entity instanceof EntityPlayer) { | if (event.entity instanceof EntityPlayer) { | ||
61行目: | 78行目: | ||
@SubscribeEvent | @SubscribeEvent | ||
− | /* | + | /*ワールドに入った時に呼ばれるイベント。ここでIExtendedEntityPropertiesを読み込む処理を呼び出す*/ |
− | public void | + | public void onEntityJoinWorld(EntityJoinWorldEvent event) { |
− | if (event. | + | if (event.world.isRemote && event.entity instanceof EntityPlayer) { |
− | + | EntityPlayer player = (EntityPlayer)event.entity; | |
− | + | PacketHandler.INSTANCE.sendToServer(new MessagePlayerJoinInAnnouncement(player)); | |
− | |||
} | } | ||
} | } | ||
− | + | @SubscribeEvent | |
− | / | + | //Dimension移動時や、リスポーン時に呼ばれるイベント。古いインスタンスと新しいインスタンスの両方を参照できる。 |
− | public void | + | public void onClonePlayer(net.minecraftforge.event.entity.player.PlayerEvent.Clone event) { |
− | if ( | + | //死亡時に呼ばれてるかどうか |
− | + | if (event.wasDeath) { | |
− | + | //古いカスタムデータ | |
− | + | IExtendedEntityProperties oldEntityProperties = event.original.getExtendedProperties(ExtendedPlayerProperties.EXT_PROP_NAME); | |
− | + | //新しいカスタムデータ | |
− | + | IExtendedEntityProperties newEntityProperties = event.entityPlayer.getExtendedProperties(ExtendedPlayerProperties.EXT_PROP_NAME); | |
+ | NBTTagCompound playerData = new NBTTagCompound(); | ||
+ | //データの吸い出し | ||
+ | oldEntityProperties.saveNBTData(playerData); | ||
+ | //データの書き込み | ||
+ | newEntityProperties.loadNBTData(playerData); | ||
+ | |||
} | } | ||
} | } | ||
88行目: | 110行目: | ||
PacketHandler.INSTANCE.sendTo(new MessagePlayerProperties(event.player), (EntityPlayerMP)event.player); | PacketHandler.INSTANCE.sendTo(new MessagePlayerProperties(event.player), (EntityPlayerMP)event.player); | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
} | } | ||
129行目: | 133行目: | ||
public final static String EXT_PROP_NAME = "samplePlayerData"; | public final static String EXT_PROP_NAME = "samplePlayerData"; | ||
− | private int sampleInt; | + | private int sampleInt = 0; |
− | private double sampleDouble; | + | private double sampleDouble = 0.0D; |
− | private boolean sampleBoolean; | + | private boolean sampleBoolean = false; |
− | private String sampleString; | + | private String sampleString = ""; |
− | private ItemStack sampleItemStack; | + | private ItemStack sampleItemStack = new ItemStack(Items.apple); |
private ItemStack[] sampleItemStacks = new ItemStack[10]; | private ItemStack[] sampleItemStacks = new ItemStack[10]; | ||
− | private NBTTagCompound sampleNBTTagCompound | + | private NBTTagCompound sampleNBTTagCompound = new NBTTagCompound(); |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
/*EntityPlayerにIExtendedEntityPropertiesを登録。登録文字列はMOD固有のものを割り当てること*/ | /*EntityPlayerにIExtendedEntityPropertiesを登録。登録文字列はMOD固有のものを割り当てること*/ | ||
210行目: | 208行目: | ||
/*初期化メソッド。今のところ使う必要はない。*/ | /*初期化メソッド。今のところ使う必要はない。*/ | ||
public void init(Entity entity, World world) {} | public void init(Entity entity, World world) {} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
/*以降、各変数のGetterおよびSetter。 | /*以降、各変数のGetterおよびSetter。 | ||
279行目: | 269行目: | ||
this.sampleNBTTagCompound = sampleNBTTagCompound; | this.sampleNBTTagCompound = sampleNBTTagCompound; | ||
} | } | ||
+ | } | ||
+ | |||
+ | </source> | ||
+ | ===CommonProxyクラス=== | ||
+ | |||
+ | <source lang = "java"> | ||
+ | |||
+ | package sampleMod; | ||
+ | |||
+ | import net.minecraft.entity.player.EntityPlayer; | ||
+ | |||
+ | public class CommonProxy { | ||
+ | |||
+ | public EntityPlayer getEntityPlayerInstance() {return null;} | ||
+ | |||
+ | } | ||
+ | |||
+ | </source> | ||
+ | |||
+ | ===ClientProxyクラス=== | ||
+ | |||
+ | <source lang = "java"> | ||
+ | |||
+ | package sampleMod; | ||
+ | |||
+ | import net.minecraft.client.Minecraft; | ||
+ | |||
+ | import net.minecraft.entity.player.EntityPlayer; | ||
+ | |||
+ | public class ClientProxy extends CommonProxy { | ||
+ | |||
+ | @Override | ||
+ | |||
+ | public EntityPlayer getEntityPlayerInstance() { | ||
+ | |||
+ | return Minecraft.getMinecraft().thePlayer; | ||
+ | |||
+ | } | ||
+ | |||
} | } | ||
301行目: | 330行目: | ||
* 第三引数:登録番号。255個まで | * 第三引数:登録番号。255個まで | ||
* 第四引数:ClientとServerのどちらに送るか。送り先*/ | * 第四引数:ClientとServerのどちらに送るか。送り先*/ | ||
− | INSTANCE.registerMessage( | + | INSTANCE.registerMessage(MessagePlayerPropertiesHandler.class, MessagePlayerProperties.class, 0, Side.CLIENT); |
+ | INSTANCE.registerMessage(MessagePlayerJoinInAnoucementHandler.class, MessagePlayerJoinInAnnouncement.class, 1, Side.SERVER); | ||
} | } | ||
} | } | ||
312行目: | 342行目: | ||
import cpw.mods.fml.common.network.ByteBufUtils; | import cpw.mods.fml.common.network.ByteBufUtils; | ||
import cpw.mods.fml.common.network.simpleimpl.IMessage; | import cpw.mods.fml.common.network.simpleimpl.IMessage; | ||
− | |||
− | |||
import io.netty.buffer.ByteBuf; | import io.netty.buffer.ByteBuf; | ||
− | |||
import net.minecraft.entity.player.EntityPlayer; | import net.minecraft.entity.player.EntityPlayer; | ||
import net.minecraft.nbt.NBTTagCompound; | import net.minecraft.nbt.NBTTagCompound; | ||
− | public class MessagePlayerProperties implements IMessage | + | public class MessagePlayerProperties implements IMessage { |
− | + | public NBTTagCompound data; | |
public MessagePlayerProperties(){} | public MessagePlayerProperties(){} | ||
340行目: | 367行目: | ||
ByteBufUtils.writeTag(buf, data); | ByteBufUtils.writeTag(buf, data); | ||
} | } | ||
+ | } | ||
+ | |||
+ | </source> | ||
+ | |||
+ | ===MessagePlayerPropertiesHandlerクラス=== | ||
+ | <source lang = "java"> | ||
+ | package sampleMod; | ||
+ | |||
+ | import cpw.mods.fml.common.network.simpleimpl.IMessage; | ||
+ | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; | ||
+ | import cpw.mods.fml.common.network.simpleimpl.MessageContext; | ||
+ | import io.netty.buffer.ByteBuf; | ||
+ | import net.minecraft.entity.player.EntityPlayer; | ||
+ | import net.minecraft.nbt.NBTTagCompound; | ||
+ | |||
+ | public class MessagePlayerPropertiesHandler implements IMessageHandler<MessagePlayerProperties, IMessage> { | ||
@Override | @Override | ||
public IMessage onMessage(MessagePlayerProperties message, MessageContext ctx) { | public IMessage onMessage(MessagePlayerProperties message, MessageContext ctx) { | ||
//Client側にIExtendedEntityPropertiesを渡す。 | //Client側にIExtendedEntityPropertiesを渡す。 | ||
− | ExtendedPlayerProperties.get( | + | ExtendedPlayerProperties.get(SampleMod.proxy.getEntityPlayerInstance()).loadNBTData(message.data); |
//REPLYは送らないので、nullを返す。 | //REPLYは送らないので、nullを返す。 | ||
return null; | return null; | ||
351行目: | 394行目: | ||
</source> | </source> | ||
+ | ===MessagePlayerJoinInAnnouncementクラス=== | ||
+ | <source lang = "java"> | ||
+ | package sampleMod; | ||
+ | |||
+ | import cpw.mods.fml.common.network.ByteBufUtils; | ||
+ | import cpw.mods.fml.common.network.simpleimpl.IMessage; | ||
+ | import io.netty.buffer.ByteBuf; | ||
+ | import net.minecraft.entity.player.EntityPlayer; | ||
+ | |||
+ | public class MessagePlayerJoinInAnnouncement implements IMessage { | ||
+ | |||
+ | private String uuid; | ||
+ | |||
+ | public MessagePlayerJoinInAnnouncement(){} | ||
+ | |||
+ | public MessagePlayerJoinInAnnouncement(EntityPlayer player) { | ||
+ | //PlayerのUUIDを文字列で取得 | ||
+ | this.uuid = player.getGameProfile().getId().toString(); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void fromBytes(ByteBuf buf) { | ||
+ | this.uuid = ByteBufUtils.readUTF8String(buf); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void toBytes(ByteBuf buf) { | ||
+ | ByteBufUtils.writeUTF8String(buf, this.uuid); | ||
+ | } | ||
+ | |||
+ | public String getUuid() { | ||
+ | return uuid; | ||
+ | } | ||
+ | |||
+ | public void setUuid(String uuid) { | ||
+ | this.uuid = uuid; | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | ===MessagePlayerJoinInAnoucementHandlerクラス=== | ||
+ | <source lang = "java"> | ||
+ | package sampleMod; | ||
+ | |||
+ | import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; | ||
+ | import cpw.mods.fml.common.network.simpleimpl.MessageContext; | ||
+ | import net.minecraft.entity.player.EntityPlayer; | ||
+ | |||
+ | public class MessagePlayerJoinInAnnouncementHandler implements IMessageHandler<MessagePlayerJoinInAnnouncement, MessagePlayerProperties> { | ||
+ | @Override | ||
+ | public MessagePlayerProperties onMessage(MessagePlayerJoinInAnnouncement message, MessageContext ctx) { | ||
+ | //UUIDの文字列を受け取る | ||
+ | String uuidString = message.getUuid(); | ||
+ | EntityPlayer player = ctx.getServerHandler().playerEntity; | ||
+ | //取得したPlayerが同一UUIDを持つか判定 | ||
+ | if (player.getGameProfile().getId().toString().equals(uuidString)) { | ||
+ | //クライアント側にデータを送る | ||
+ | return new MessagePlayerProperties(player); | ||
+ | } | ||
+ | //UUIDが違っていた場合、同期処理を呼ばない | ||
+ | return null; | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
==解説== | ==解説== | ||
細かい説明はソースコード内に付記したので、そちらを参照のこと。 | 細かい説明はソースコード内に付記したので、そちらを参照のこと。 | ||
358行目: | 465行目: | ||
ExtendedPlayerProperties.get(playerインスタンス).getSampleInt()という形でデータを呼び出す。<br> | ExtendedPlayerProperties.get(playerインスタンス).getSampleInt()という形でデータを呼び出す。<br> | ||
ExtendedPlayerProperties.get(playerインスタンス).setSampleInt(sample)という形でデータを書き込む。<br> | ExtendedPlayerProperties.get(playerインスタンス).setSampleInt(sample)という形でデータを書き込む。<br> | ||
− | + | 死亡時等でカスタムデータが初期化されるので、CloneEventでデータを新しいインスタンスに移行し、EntityJoinWorldEventとRespawnEventで、クライアント側にデータを送って同期させている。 | |
− |
2018年7月22日 (日) 21:57時点における最新版
この記事は"Minecraft Forge Universal 10.12.1.1090~"を前提MODとしています。 |
この記事は執筆中です。加筆してくださる人を募集しています。 |
目次
- 1 プレイヤーへのカスタムデータの追加
- 2 ソースコード
- 2.1 SampleModクラス
- 2.2 SampleEntityPropertiesEventHandlerクラス
- 2.3 ExtendedPlayerPropertiesクラス
- 2.4 CommonProxyクラス
- 2.5 ClientProxyクラス
- 2.6 PacketHandlerクラス
- 2.7 MessagePlayerPropertiesクラス
- 2.8 MessagePlayerPropertiesHandlerクラス
- 2.9 MessagePlayerJoinInAnnouncementクラス
- 2.10 MessagePlayerJoinInAnoucementHandlerクラス
- 3 解説
プレイヤーへのカスタムデータの追加[編集]
各プレイヤーにカスタムデータを追加する。 方法としては、EntityクラスのgetEntityDataメソッドの利用か、ForgeのIExtendedEntityPropertiesインターフェースの利用の二通りある。
このチュートリアルでは、IExtendedEntityPropertiesによる実装方法を解説する。
ソースコード[編集]
SampleModクラス[編集]
package sampleMod; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.PlayerEvent; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; import java.util.HashMap; import java.util.Map; //FMLのパケットシステムはForge 10.12.1.1090以降でないと動作しないので、dependenciesでそれ以降を指定すること。 @Mod(modid = "SampleMod", name = "SampleMod", version = "1.0", dependencies = "required-after:Forge@[10.12.1.1090,)", useMetadata = true) public class SampleMod { @SidedProxy(clientSide = "sampleMod.ClientProxy", serverSide = "sampleMod.CommonProxy") public static CommonProxy proxy; @EventHandler public void preInit(FMLPreInitializationEvent event) { //Messageの登録呼び出し PacketHandler.init(); } @EventHandler public void init(FMLInitializationEvent event) { //二箇所に登録するので、先にインスタンスを生成しておく。 SampleEntityPropertiesEventHandler sampleEntityPropertiesEventHandler = new SampleEntityPropertiesEventHandler(); //Forge Eventの登録。EntityEvent.EntityConstructingとLivingDeathEventとEntityJoinWorldEvent MinecraftForge.EVENT_BUS.register(sampleEntityPropertiesEventHandler); //FML Eventの登録。PlayerRespawnEvent FMLCommonHandler.instance().bus().register(sampleEntityPropertiesEventHandler); } }
SampleEntityPropertiesEventHandlerクラス[編集]
package sampleMod; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.PlayerEvent; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.IExtendedEntityProperties; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent; public class SampleEntityPropertiesEventHandler { /*IExtendedEntityPropertiesを登録する処理を呼び出す*/ @SubscribeEvent public void onEntityConstructing(EntityEvent.EntityConstructing event) { if (event.entity instanceof EntityPlayer) { ExtendedPlayerProperties.register((EntityPlayer)event.entity); } } @SubscribeEvent /*ワールドに入った時に呼ばれるイベント。ここでIExtendedEntityPropertiesを読み込む処理を呼び出す*/ public void onEntityJoinWorld(EntityJoinWorldEvent event) { if (event.world.isRemote && event.entity instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer)event.entity; PacketHandler.INSTANCE.sendToServer(new MessagePlayerJoinInAnnouncement(player)); } } @SubscribeEvent //Dimension移動時や、リスポーン時に呼ばれるイベント。古いインスタンスと新しいインスタンスの両方を参照できる。 public void onClonePlayer(net.minecraftforge.event.entity.player.PlayerEvent.Clone event) { //死亡時に呼ばれてるかどうか if (event.wasDeath) { //古いカスタムデータ IExtendedEntityProperties oldEntityProperties = event.original.getExtendedProperties(ExtendedPlayerProperties.EXT_PROP_NAME); //新しいカスタムデータ IExtendedEntityProperties newEntityProperties = event.entityPlayer.getExtendedProperties(ExtendedPlayerProperties.EXT_PROP_NAME); NBTTagCompound playerData = new NBTTagCompound(); //データの吸い出し oldEntityProperties.saveNBTData(playerData); //データの書き込み newEntityProperties.loadNBTData(playerData); } } @SubscribeEvent /*リスポーン時に呼ばれるイベント。Serverとの同期を取る*/ public void respawnEvent(PlayerEvent.PlayerRespawnEvent event) { if (!event.player.worldObj.isRemote) { PacketHandler.INSTANCE.sendTo(new MessagePlayerProperties(event.player), (EntityPlayerMP)event.player); } } }
ExtendedPlayerPropertiesクラス[編集]
package sampleMod; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.world.World; import net.minecraftforge.common.IExtendedEntityProperties; import net.minecraftforge.common.util.Constants; public class ExtendedPlayerProperties implements IExtendedEntityProperties { /* MOD固有の文字列。EntityPlayerに登録時に使用。 MOD内で複数のIExtendedEntityPropertiesを使う場合は、別の文字列をそれぞれ割り当てること。*/ public final static String EXT_PROP_NAME = "samplePlayerData"; private int sampleInt = 0; private double sampleDouble = 0.0D; private boolean sampleBoolean = false; private String sampleString = ""; private ItemStack sampleItemStack = new ItemStack(Items.apple); private ItemStack[] sampleItemStacks = new ItemStack[10]; private NBTTagCompound sampleNBTTagCompound = new NBTTagCompound(); /*EntityPlayerにIExtendedEntityPropertiesを登録。登録文字列はMOD固有のものを割り当てること*/ public static void register(EntityPlayer player) { player.registerExtendedProperties(EXT_PROP_NAME, new ExtendedPlayerProperties()); } /*IExtendedEntityPropertiesをEntityPlayerインスタンスから取得する*/ public static ExtendedPlayerProperties get(EntityPlayer player) { return (ExtendedPlayerProperties)player.getExtendedProperties(EXT_PROP_NAME); } @Override public void saveNBTData(NBTTagCompound compound) { NBTTagCompound nbt = new NBTTagCompound(); nbt.setInteger("sampleInt", this.sampleInt); nbt.setDouble("sampleDouble", this.sampleDouble); nbt.setBoolean("sampleBoolean", this.sampleBoolean); nbt.setString("sampleString", this.sampleString); nbt.setTag("sampleTag", this.sampleNBTTagCompound); //ItemStackの保存 NBTTagCompound itemNBT = new NBTTagCompound(); this.sampleItemStack.writeToNBT(itemNBT); nbt.setTag("sampleItemStack", itemNBT); //ItemStackの配列の保存 NBTTagList itemsTagList = new NBTTagList(); for (int i = 0; i < this.sampleItemStacks.length; ++i) { if (this.sampleItemStacks[i] != null) { NBTTagCompound var4 = new NBTTagCompound(); var4.setByte("Slot", (byte)i); this.sampleItemStacks[i].writeToNBT(var4); itemsTagList.appendTag(var4); } } nbt.setTag("Items", itemsTagList); compound.setTag(EXT_PROP_NAME, nbt); } @Override public void loadNBTData(NBTTagCompound compound) { NBTTagCompound nbt = (NBTTagCompound)compound.getTag(EXT_PROP_NAME); this.sampleInt = nbt.getInteger("sampleInt"); this.sampleDouble = nbt.getDouble("sampleDouble"); this.sampleBoolean = nbt.getBoolean("sampleBoolean"); this.sampleString = nbt.getString("sampleString"); this.sampleNBTTagCompound = nbt.getCompoundTag("sampleTag"); //ItemStackの読み込み this.sampleItemStack = ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("sampleItemStack")); //ItemStackの配列の読み込み NBTTagList itemsTagList = nbt.getTagList("Items", Constants.NBT.TAG_COMPOUND); this.sampleItemStacks = new ItemStack[10]; for (int i = 0; i < itemsTagList.tagCount(); ++i) { NBTTagCompound var4 = itemsTagList.getCompoundTagAt(i); int slot = var4.getByte("Slot") & 255; if (slot >= 0 && slot < this.sampleItemStacks.length) { this.sampleItemStacks[slot] = ItemStack.loadItemStackFromNBT(var4); } } } @Override /*初期化メソッド。今のところ使う必要はない。*/ public void init(Entity entity, World world) {} /*以降、各変数のGetterおよびSetter。 * 使い方としては、EntityPlayerのインスタンスが取得できるメソッド内で、 * ExtendedPlayerProperties.get(playerインスタンス).setSampleInt(sample) * と呼び出す。*/ public int getSampleInt() { return sampleInt; } public void setSampleInt(int sampleInt) { this.sampleInt = sampleInt; } public double getSampleDouble() { return sampleDouble; } public void setSampleDouble(double sampleDouble) { this.sampleDouble = sampleDouble; } public boolean isSampleBoolean() { return sampleBoolean; } public void setSampleBoolean(boolean sampleBoolean) { this.sampleBoolean = sampleBoolean; } public String getSampleString() { return sampleString; } public void setSampleString(String sampleString) { this.sampleString = sampleString; } public ItemStack getSampleItemStack() { return sampleItemStack; } public void setSampleItemStack(ItemStack sampleItemStack) { this.sampleItemStack = sampleItemStack; } public ItemStack[] getSampleItemStacks() { return sampleItemStacks; } public void setSampleItemStacks(ItemStack[] sampleItemStacks) { this.sampleItemStacks = sampleItemStacks; } public NBTTagCompound getSampleNBTTagCompound() { return sampleNBTTagCompound; } public void setSampleNBTTagCompound(NBTTagCompound sampleNBTTagCompound) { this.sampleNBTTagCompound = sampleNBTTagCompound; } }
CommonProxyクラス[編集]
package sampleMod; import net.minecraft.entity.player.EntityPlayer; public class CommonProxy { public EntityPlayer getEntityPlayerInstance() {return null;} }
ClientProxyクラス[編集]
package sampleMod; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; public class ClientProxy extends CommonProxy { @Override public EntityPlayer getEntityPlayerInstance() { return Minecraft.getMinecraft().thePlayer; } }
PacketHandlerクラス[編集]
package sampleMod; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; import cpw.mods.fml.relauncher.Side; public class PacketHandler { /*MOD固有のSimpleNetworkWrapperを取得。 * 文字列は他のMODと被らないようにMOD_IDを指定しておくと良い*/ public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel("samplemod"); public static void init() { /*Messageクラスの登録。 * 第一引数:IMessageHandlerクラス * 第二引数:送るMessageクラス * 第三引数:登録番号。255個まで * 第四引数:ClientとServerのどちらに送るか。送り先*/ INSTANCE.registerMessage(MessagePlayerPropertiesHandler.class, MessagePlayerProperties.class, 0, Side.CLIENT); INSTANCE.registerMessage(MessagePlayerJoinInAnoucementHandler.class, MessagePlayerJoinInAnnouncement.class, 1, Side.SERVER); } }
MessagePlayerPropertiesクラス[編集]
package sampleMod; import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; public class MessagePlayerProperties implements IMessage { public NBTTagCompound data; public MessagePlayerProperties(){} public MessagePlayerProperties(EntityPlayer entityPlayer) { this.data = new NBTTagCompound(); //EntityPlayerからIExtendedEntityPropertiesを取得。 ExtendedPlayerProperties.get(entityPlayer).saveNBTData(data); } @Override public void fromBytes(ByteBuf buf) { data = ByteBufUtils.readTag(buf); } @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeTag(buf, data); } }
MessagePlayerPropertiesHandlerクラス[編集]
package sampleMod; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; public class MessagePlayerPropertiesHandler implements IMessageHandler<MessagePlayerProperties, IMessage> { @Override public IMessage onMessage(MessagePlayerProperties message, MessageContext ctx) { //Client側にIExtendedEntityPropertiesを渡す。 ExtendedPlayerProperties.get(SampleMod.proxy.getEntityPlayerInstance()).loadNBTData(message.data); //REPLYは送らないので、nullを返す。 return null; } }
MessagePlayerJoinInAnnouncementクラス[編集]
package sampleMod; import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; public class MessagePlayerJoinInAnnouncement implements IMessage { private String uuid; public MessagePlayerJoinInAnnouncement(){} public MessagePlayerJoinInAnnouncement(EntityPlayer player) { //PlayerのUUIDを文字列で取得 this.uuid = player.getGameProfile().getId().toString(); } @Override public void fromBytes(ByteBuf buf) { this.uuid = ByteBufUtils.readUTF8String(buf); } @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, this.uuid); } public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; } }
MessagePlayerJoinInAnoucementHandlerクラス[編集]
package sampleMod; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import net.minecraft.entity.player.EntityPlayer; public class MessagePlayerJoinInAnnouncementHandler implements IMessageHandler<MessagePlayerJoinInAnnouncement, MessagePlayerProperties> { @Override public MessagePlayerProperties onMessage(MessagePlayerJoinInAnnouncement message, MessageContext ctx) { //UUIDの文字列を受け取る String uuidString = message.getUuid(); EntityPlayer player = ctx.getServerHandler().playerEntity; //取得したPlayerが同一UUIDを持つか判定 if (player.getGameProfile().getId().toString().equals(uuidString)) { //クライアント側にデータを送る return new MessagePlayerProperties(player); } //UUIDが違っていた場合、同期処理を呼ばない return null; } }
解説[編集]
細かい説明はソースコード内に付記したので、そちらを参照のこと。
使用の流れを簡単に書くと、
EntityEvent.EntityConstructingにて、IExtendedEntityPropertiesを登録。
ExtendedPlayerProperties.get(playerインスタンス).getSampleInt()という形でデータを呼び出す。
ExtendedPlayerProperties.get(playerインスタンス).setSampleInt(sample)という形でデータを書き込む。
死亡時等でカスタムデータが初期化されるので、CloneEventでデータを新しいインスタンスに移行し、EntityJoinWorldEventとRespawnEventで、クライアント側にデータを送って同期させている。