-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathPacketPipeline.java
More file actions
210 lines (186 loc) · 7.61 KB
/
Copy pathPacketPipeline.java
File metadata and controls
210 lines (186 loc) · 7.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package chestviewer;
import com.google.common.collect.Lists;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.FMLEmbeddedChannel;
import cpw.mods.fml.common.network.FMLOutboundHandler;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetHandlerPlayServer;
import java.util.*;
/*
* https://github.com/reginn/Tutorial-Packetの完全なるコピペ
* 圧倒的感謝・・・っ!
*/
/*
* http://www.minecraftforge.net/wiki/Netty_Packet_Handlingにあるコードをほぼそのまま使用.
* コメントは説明用に書き変えてます.
* AKさんが日本語訳を作ってくれました.
* http://forum.minecraftuser.jp/viewtopic.php?f=21&t=18255
*/
/*
* パケットを扱う総合的なクラス.
* パケットの登録から送受信を担う.
*/
@ChannelHandler.Sharable
public class PacketPipeline extends MessageToMessageCodec<FMLProxyPacket, AbstractPacket>
{
private EnumMap<Side, FMLEmbeddedChannel> channels;
private LinkedList<Class<? extends AbstractPacket>> packets = Lists.newLinkedList();
private boolean isPostInitialised = false;
/*
* パケットを登録するメソッド.
* AbstractPacketクラスを継承したクラスを登録する.
*/
public boolean registerPacket(Class<? extends AbstractPacket> clazz)
{
if (this.packets.size() > 256 | this.packets.contains(clazz) | this.isPostInitialised)
{
return false;
}
this.packets.add(clazz);
return true;
}
/*
* PacketPipelineの初期化を行うメソッド.
* 具体的にはNetworkRegistryに新しいチャンネルを登録する.
* 今回は引数をチャンネル名として登録する.
*/
public void init(String channelName)
{
this.channels = NetworkRegistry.INSTANCE.newChannel(channelName, this);
}
/*
* PacketPipelineに登録されたパケットを整理するメソッド.
* FMLPostInitializationで呼ぶ必要がある.
*/
public void postInit()
{
if (this.isPostInitialised)
{
return;
}
this.isPostInitialised = true;
Collections.sort(this.packets, new Comparator<Class<? extends AbstractPacket>>()
{
@Override
public int compare(Class<? extends AbstractPacket> clazz1, Class<? extends AbstractPacket> clazz2)
{
int com = String.CASE_INSENSITIVE_ORDER.compare(clazz1.getCanonicalName(), clazz2.getCanonicalName());
if (com == 0)
{
com = clazz1.getCanonicalName().compareTo(clazz2.getCanonicalName());
}
return com;
}
});
}
/*
* 送るパケットをバイト列に書きだすメソッド.
*/
@Override
protected void encode(ChannelHandlerContext ctx, AbstractPacket msg, List<Object> out) throws Exception
{
ByteBuf buffer = Unpooled.buffer();
Class<? extends AbstractPacket> clazz = msg.getClass();
if (!this.packets.contains(msg.getClass()))
{
throw new NullPointerException("No Packet Registered for: " + msg.getClass().getCanonicalName());
}
byte discriminator = (byte) this.packets.indexOf(clazz);
buffer.writeByte(discriminator);
msg.encodeInto(ctx, buffer);
FMLProxyPacket proxyPacket = new FMLProxyPacket(buffer.copy(), ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get());
out.add(proxyPacket);
}
/*
* 受け取ったパケットを読み込んで実行するメソッド.
* ここでパケットのhandleClient/ServerSide()が実行される.
*/
@Override
protected void decode(ChannelHandlerContext ctx, FMLProxyPacket msg, List<Object> out) throws Exception
{
ByteBuf payload = msg.payload();
byte discriminator = payload.readByte();
Class<? extends AbstractPacket> clazz = this.packets.get(discriminator);
if (clazz == null)
{
throw new NullPointerException("No packet registered for discriminator: " + discriminator);
}
AbstractPacket pkt = clazz.newInstance();
pkt.decodeInto(ctx, payload.slice());
EntityPlayer player;
switch (FMLCommonHandler.instance().getEffectiveSide())
{
case CLIENT:
player = this.getClientPlayer();
pkt.handleClientSide(player);
break;
case SERVER:
INetHandler netHandler = ctx.channel().attr(NetworkRegistry.NET_HANDLER).get();
player = ((NetHandlerPlayServer)netHandler).playerEntity;
pkt.handleServerSide(player);
break;
default:
}
out.add(pkt);
}
@SideOnly(Side.CLIENT)
private EntityPlayer getClientPlayer()
{
return Minecraft.getMinecraft().thePlayer;
}
/*
* 全プレイヤーにパケットを送るメソッド.
*/
public void sendPacketToAllPlayer(AbstractPacket packet)
{
this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL);
this.channels.get(Side.SERVER).writeAndFlush(packet);
}
/*
* 特定プレイヤーにパケットを送るメソッド.
*/
public void sendPacketToPlayer(AbstractPacket packet, EntityPlayerMP player)
{
this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER);
this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player);
this.channels.get(Side.SERVER).writeAndFlush(packet);
}
/*
* 特定位置周囲にいるプレイヤーにパケットを送るメソッド.
*/
public void sendPacketToAllAround(AbstractPacket packet, NetworkRegistry.TargetPoint point)
{
this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT);
this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
this.channels.get(Side.SERVER).writeAndFlush(packet);
}
/*
* 特定ディメンションにいるプレイヤー全てにパケットを送るメソッド.
*/
public void sendPacketToAllInDimension(AbstractPacket packet, int dimensionId)
{
this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION);
this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimensionId);
this.channels.get(Side.SERVER).writeAndFlush(packet);
}
/*
* クライアントからサーバーにパケットを送るメソッド.
*/
public void sendPacketToServer(AbstractPacket packet)
{
this.channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER);
this.channels.get(Side.CLIENT).writeAndFlush(packet);
}
}