📄 clientthread.java
字号:
if (opcode == Opcodes.C_OPCODE_CHANGECHAR
|| opcode == Opcodes.C_OPCODE_DROPITEM
|| opcode == Opcodes.C_OPCODE_DELETEINVENTORYITEM) {
_handler.handlePacket(data, _activeChar);
} else if (opcode == Opcodes.C_OPCODE_MOVECHAR) {
// 移動はなるべく確実に行う為、移動専用スレッドへ受け渡し
movePacket.requestWork(data);
} else {
// パケット処理スレッドへ受け渡し
hcPacket.requestWork(data);
}
}
} catch (Throwable e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
} finally {
try {
if (_activeChar != null) {
quitGame(_activeChar);
synchronized (_activeChar) {
// キャラクターをワールド内から除去
_activeChar.logout();
setActiveChar(null);
}
}
// 念のため送信
sendPacket(new S_Disconnect());
StreamUtil.close(_out, _in);
} catch (Exception e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
} finally {
LoginController.getInstance().logout(this);
}
}
_csocket = null;
_log.fine("Server thread[C] stopped");
if (_kick < 1) {
_log.info("帳號 " + getAccountName() + " (" + _hostname
+ ") 客戶端連線結束。");
l1j.eric.gui.J_Main.getInstance().addConsolPost("使用記憶體: " + SystemUtil.getUsedMemoryMB() + "MB");
l1j.eric.gui.J_Main.getInstance().addConsolPost("等待玩家連線...");
}
return;
}
private int _kick = 0;
public void kick() {
sendPacket(new S_Disconnect());
_kick = 1;
StreamUtil.close(_out, _in);
}
private static final int M_CAPACITY = 3; // 移動要求を一辺に受け付ける最大容量
private static final int H_CAPACITY = 2;// 行動要求を一辺に受け付ける最大容量
// キャラクターの行動処理スレッド
class HcPacket implements Runnable {
private final Queue<byte[]> _queue;
private PacketHandler _handler;
public HcPacket() {
_queue = new ConcurrentLinkedQueue<byte[]>();
_handler = new PacketHandler(ClientThread.this);
}
public HcPacket(int capacity) {
_queue = new LinkedBlockingQueue<byte[]>(capacity);
_handler = new PacketHandler(ClientThread.this);
}
public void requestWork(byte data[]) {
_queue.offer(data);
}
@Override
public void run() {
byte[] data;
while (_csocket != null) {
data = _queue.poll();
if (data != null) {
try {
_handler.handlePacket(data, _activeChar);
} catch (Exception e) {}
} else {
try {
Thread.sleep(10);
} catch (Exception e) {}
}
}
return;
}
}
private static Timer _observerTimer = new Timer();
// クライアントスレッドの監視タイマー
class ClientThreadObserver extends TimerTask {
private int _checkct = 1;
private final int _disconnectTimeMillis;
public ClientThreadObserver(int disconnectTimeMillis) {
_disconnectTimeMillis = disconnectTimeMillis;
}
public void start() {
_observerTimer.scheduleAtFixedRate(ClientThreadObserver.this, 0,
_disconnectTimeMillis);
}
@Override
public void run() {
try {
if (_csocket == null) {
cancel();
return;
}
if (_checkct > 0) {
_checkct = 0;
return;
}
if (_activeChar == null // キャラクター選択前
|| _activeChar != null && !_activeChar.isPrivateShop()) { // 個人商店中
kick();
_log.warning("由於等待連線時間過久導致來自於 (" + _hostname
+ ") 的連線被強制中斷。");
cancel();
return;
}
} catch (Exception e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
cancel();
}
}
public void packetReceived() {
_checkct++;
}
}
@Override
public void sendPacket(ServerBasePacket packet) {
synchronized (this) {
try {
byte abyte0[] = packet.getContent();
char ac[] = new char[abyte0.length];
ac = UChar8.fromArray(abyte0);
ac = LineageEncryption.encrypt(ac, _clkey);
abyte0 = UByte8.fromArray(ac);
int j = abyte0.length + 2;
_out.write(j & 0xff);
_out.write(j >> 8 & 0xff);
_out.write(abyte0);
_out.flush();
} catch (Exception e) {}
}
}
public void close() throws IOException {
_csocket.close();
}
public void setActiveChar(L1PcInstance pc) {
_activeChar = pc;
}
public L1PcInstance getActiveChar() {
return _activeChar;
}
public void setAccount(Account account) {
_account = account;
}
public Account getAccount() {
return _account;
}
public String getAccountName() {
if (_account == null) {
return null;
}
return _account.getName();
}
public static void quitGame(L1PcInstance pc) {
// 死亡していたら街に戻し、空腹状態にする
if (pc.isDead()) {
int[] loc = Getback.GetBack_Location(pc, true);
pc.setX(loc[0]);
pc.setY(loc[1]);
pc.setMap((short) loc[2]);
pc.setCurrentHp(pc.getLevel());
pc.set_food(40);
}
// トレードを中止する
if (pc.getTradeID() != 0) { // トレード中
L1Trade trade = new L1Trade();
trade.TradeCancel(pc);
}
// 決闘を中止する
if (pc.getFightId() != 0) {
pc.setFightId(0);
L1PcInstance fightPc = (L1PcInstance) L1World.getInstance()
.findObject(pc.getFightId());
if (fightPc != null) {
fightPc.setFightId(0);
fightPc.sendPackets(new S_PacketBox(S_PacketBox.MSG_DUEL,
0, 0));
}
}
// パーティーを抜ける
if (pc.isInParty()) { // パーティー中
pc.getParty().leaveMember(pc);
}
// チャットパーティーを抜ける
if (pc.isInChatParty()) { // チャットパーティー中
pc.getChatParty().leaveMember(pc);
}
// ペットをワールドマップ上から消す
// サモンの表示名を変更する
Object[] petList = pc.getPetList().values().toArray();
for (Object petObject : petList) {
if (petObject instanceof L1PetInstance) {
L1PetInstance pet = (L1PetInstance) petObject;
pet.dropItem();
pc.getPetList().remove(pet.getId());
pet.deleteMe();
}
if (petObject instanceof L1SummonInstance) {
L1SummonInstance summon = (L1SummonInstance) petObject;
for (L1PcInstance visiblePc : L1World.getInstance()
.getVisiblePlayer(summon)) {
visiblePc.sendPackets(new S_SummonPack(summon, visiblePc,
false));
}
}
}
// マジックドールをワールドマップ上から消す
Object[] dollList = pc.getDollList().values().toArray();
for (Object dollObject : dollList) {
L1DollInstance doll = (L1DollInstance) dollObject;
doll.deleteDoll();
}
// 従者をワールドマップ上から消し、同地点に再出現させる
Object[] followerList = pc.getFollowerList().values().toArray();
for (Object followerObject : followerList) {
L1FollowerInstance follower = (L1FollowerInstance) followerObject;
follower.setParalyzed(true);
follower.spawn(follower.getNpcTemplate().get_npcId(),
follower.getX(), follower.getY(), follower.getHeading(),
follower.getMapId());
follower.deleteMe();
}
// エンチャントをDBのcharacter_buffに保存する
CharBuffTable.DeleteBuff(pc);
CharBuffTable.SaveBuff(pc);
pc.clearSkillEffectTimer();
// pcのモニターをstopする。
pc.stopEtcMonitor();
// オンライン状態をOFFにし、DBにキャラクター情報を書き込む
pc.setOnlineStatus(0);
l1j.eric.gui.J_Main.getInstance().delPlayerTable(pc.getName());//GUI
try {
pc.save();
pc.saveInventory();
} catch (Exception e) {
_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -