/*
* Copyright (C) 2004-2015 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* L2J DataPack is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package handlers.admincommandhandlers;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.LinkedList;
import java.util.StringTokenizer;
import com.l2jserver.gameserver.GameServer;
import com.l2jserver.gameserver.ThreadPoolManager;
import com.l2jserver.gameserver.cache.HtmCache;
import com.l2jserver.gameserver.handler.IAdminCommandHandler;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Playable;
import com.l2jserver.gameserver.model.actor.instance.L2BoatInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.clientpackets.L2GameClientPacket;
import com.l2jserver.gameserver.network.serverpackets.AdminForgePacket;
import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
import com.l2jserver.mmocore.NioNetStringBuffer;
/**
* This class handles commands for gm to forge packets
* @author Maktakien, HorridoJoho
*/
public final class AdminPForge implements IAdminCommandHandler
{
private static final String[] ADMIN_COMMANDS =
{
"admin_forge",
"admin_forge_values",
"admin_forge_send"
};
private String[] getOpCodes(StringTokenizer st)
{
Collection opCodes = null;
while (st.hasMoreTokens())
{
String token = st.nextToken();
if (";".equals(token))
{
break;
}
if (opCodes == null)
{
opCodes = new LinkedList<>();
}
opCodes.add(token);
}
if (opCodes == null)
{
return null;
}
return opCodes.toArray(new String[opCodes.size()]);
}
private boolean validateOpCodes(String[] opCodes)
{
if ((opCodes == null) || (opCodes.length == 0) || (opCodes.length > 3))
{
return false;
}
for (int i = 0; i < opCodes.length; ++i)
{
final String opCode = opCodes[i];
long opCodeLong;
try
{
opCodeLong = Long.parseLong(opCode);
}
catch (Exception e)
{
if (i > 0)
{
return true;
}
return false;
}
if (opCodeLong < 0)
{
return false;
}
if ((i == 0) && (opCodeLong > 255))
{
return false;
}
else if ((i == 1) && (opCodeLong > 65535))
{
return false;
}
else if ((i == 2) && (opCodeLong > 4294967295L))
{
return false;
}
}
return true;
}
private boolean validateFormat(String format)
{
for (int chIdx = 0; chIdx < format.length(); ++chIdx)
{
switch (format.charAt(chIdx))
{
case 'b':
case 'B':
case 'x':
case 'X':
// array
break;
case 'c':
case 'C':
// byte
break;
case 'h':
case 'H':
// word
break;
case 'd':
case 'D':
// dword
break;
case 'q':
case 'Q':
// qword
break;
case 'f':
case 'F':
// double
break;
case 's':
case 'S':
// string
break;
default:
return false;
}
}
return true;
}
private boolean validateMethod(String method)
{
switch (method)
{
case "sc":
case "sb":
case "cs":
return true;
}
return false;
}
private void showValuesUsage(L2PcInstance activeChar)
{
activeChar.sendMessage("Usage: //forge_values opcode1[ opcode2[ opcode3]] ;[ format]");
showMainPage(activeChar);
}
private void showSendUsage(L2PcInstance activeChar, String[] opCodes, String format)
{
activeChar.sendMessage("Usage: //forge_send sc|sb|cs opcode1[;opcode2[;opcode3]][ format value1 ... valueN] ");
if (opCodes == null)
{
showMainPage(activeChar);
}
else
{
showValuesPage(activeChar, opCodes, format);
}
}
private void showMainPage(L2PcInstance activeChar)
{
AdminHtml.showAdminHtml(activeChar, "pforge/main.htm");
}
private void showValuesPage(L2PcInstance activeChar, String[] opCodes, String format)
{
String sendBypass = null;
String valuesHtml = HtmCache.getInstance().getHtmForce(activeChar.getHtmlPrefix(), "data/html/admin/pforge/values.htm");
if (opCodes.length == 3)
{
valuesHtml = valuesHtml.replace("%opformat%", "chd");
sendBypass = opCodes[0] + ";" + opCodes[1] + ";" + opCodes[2];
}
else if (opCodes.length == 2)
{
valuesHtml = valuesHtml.replace("%opformat%", "ch");
sendBypass = opCodes[0] + ";" + opCodes[1];
}
else
{
valuesHtml = valuesHtml.replace("%opformat%", "c");
sendBypass = opCodes[0];
}
valuesHtml = valuesHtml.replace("%opcodes%", sendBypass);
String editorsHtml = "";
if (format == null)
{
valuesHtml = valuesHtml.replace("%format%", "");
editorsHtml = "";
}
else
{
valuesHtml = valuesHtml.replace("%format%", format);
sendBypass += " " + format;
String editorTemplate = HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/admin/pforge/inc/editor.htm");
if (editorTemplate != null)
{
StringBuilder singleCharSequence = new StringBuilder(1);
singleCharSequence.append(' ');
for (int chIdx = 0; chIdx < format.length(); ++chIdx)
{
char ch = format.charAt(chIdx);
singleCharSequence.setCharAt(0, ch);
editorsHtml += editorTemplate.replace("%format%", singleCharSequence).replace("%editor_index%", String.valueOf(chIdx));
sendBypass += " $v" + chIdx;
}
}
else
{
editorsHtml = "";
}
}
valuesHtml = valuesHtml.replace("%editors%", editorsHtml);
valuesHtml = valuesHtml.replace("%send_bypass%", sendBypass);
activeChar.sendPacket(new NpcHtmlMessage(valuesHtml));
}
@Override
public boolean useAdminCommand(String command, L2PcInstance activeChar)
{
if (command.equals("admin_forge"))
{
showMainPage(activeChar);
}
else if (command.startsWith("admin_forge_values "))
{
try
{
StringTokenizer st = new StringTokenizer(command);
st.nextToken(); // skip command token
if (!st.hasMoreTokens())
{
showValuesUsage(activeChar);
return false;
}
String[] opCodes = getOpCodes(st);
if (!validateOpCodes(opCodes))
{
activeChar.sendMessage("Invalid op codes!");
showValuesUsage(activeChar);
return false;
}
String format = null;
if (st.hasMoreTokens())
{
format = st.nextToken();
if (!validateFormat(format))
{
activeChar.sendMessage("Format invalid!");
showValuesUsage(activeChar);
return false;
}
}
showValuesPage(activeChar, opCodes, format);
}
catch (Exception e)
{
e.printStackTrace();
showValuesUsage(activeChar);
return false;
}
}
else if (command.startsWith("admin_forge_send "))
{
try
{
StringTokenizer st = new StringTokenizer(command);
st.nextToken(); // skip command token
if (!st.hasMoreTokens())
{
showSendUsage(activeChar, null, null);
return false;
}
String method = st.nextToken();
if (!validateMethod(method))
{
activeChar.sendMessage("Invalid method!");
showSendUsage(activeChar, null, null);
return false;
}
String[] opCodes = st.nextToken().split(";");
if (!validateOpCodes(opCodes))
{
activeChar.sendMessage("Invalid op codes!");
showSendUsage(activeChar, null, null);
return false;
}
String format = null;
if (st.hasMoreTokens())
{
format = st.nextToken();
if (!validateFormat(format))
{
activeChar.sendMessage("Format invalid!");
showSendUsage(activeChar, null, null);
return false;
}
}
AdminForgePacket afp = null;
ByteBuffer bb = null;
for (int i = 0; i < opCodes.length; ++i)
{
char type;
if (i == 0)
{
type = 'c';
}
else if (i == 1)
{
type = 'h';
}
else
{
type = 'd';
}
if (method.equals("sc") || method.equals("sb"))
{
if (afp == null)
{
afp = new AdminForgePacket();
}
afp.addPart((byte) type, opCodes[i]);
}
else
{
if (bb == null)
{
bb = ByteBuffer.allocate(32767);
}
write((byte) type, opCodes[i], bb);
}
}
if (format != null)
{
for (int i = 0; i < format.length(); ++i)
{
if (!st.hasMoreTokens())
{
activeChar.sendMessage("Not enough values!");
showSendUsage(activeChar, null, null);
return false;
}
L2Object target = null;
L2BoatInstance boat = null;
String value = st.nextToken();
switch (value)
{
case "$oid":
value = String.valueOf(activeChar.getObjectId());
break;
case "$boid":
boat = activeChar.getBoat();
if (boat != null)
{
value = String.valueOf(boat.getObjectId());
}
else
{
value = "0";
}
break;
case "$title":
value = activeChar.getTitle();
break;
case "$name":
value = activeChar.getName();
break;
case "$x":
value = String.valueOf(activeChar.getX());
break;
case "$y":
value = String.valueOf(activeChar.getY());
break;
case "$z":
value = String.valueOf(activeChar.getZ());
break;
case "$heading":
value = String.valueOf(activeChar.getHeading());
break;
case "$toid":
value = String.valueOf(activeChar.getTargetId());
break;
case "$tboid":
target = activeChar.getTarget();
if ((target != null) && (target instanceof L2Playable))
{
boat = ((L2Playable) target).getActingPlayer().getBoat();
if (boat != null)
{
value = String.valueOf(boat.getObjectId());
}
else
{
value = "0";
}
}
break;
case "$ttitle":
target = activeChar.getTarget();
if ((target != null) && (target instanceof L2Character))
{
value = String.valueOf(((L2Character) target).getTitle());
}
else
{
value = "";
}
break;
case "$tname":
target = activeChar.getTarget();
if (target != null)
{
value = String.valueOf(target.getName());
}
else
{
value = "";
}
break;
case "$tx":
target = activeChar.getTarget();
if (target != null)
{
value = String.valueOf(target.getX());
}
else
{
value = "0";
}
break;
case "$ty":
target = activeChar.getTarget();
if (target != null)
{
value = String.valueOf(target.getY());
}
else
{
value = "0";
}
break;
case "$tz":
target = activeChar.getTarget();
if (target != null)
{
value = String.valueOf(target.getZ());
}
else
{
value = "0";
}
break;
case "$theading":
target = activeChar.getTarget();
if (target != null)
{
value = String.valueOf(target.getHeading());
}
else
{
value = "0";
}
break;
}
if (method.equals("sc") || method.equals("sb"))
{
if (afp != null)
{
afp.addPart((byte) format.charAt(i), value);
}
}
else
{
write((byte) format.charAt(i), value, bb);
}
}
}
if (method.equals("sc"))
{
activeChar.sendPacket(afp);
}
else if (method.equals("sb"))
{
activeChar.broadcastPacket(afp);
}
else if (bb != null)
{
bb.flip();
L2GameClientPacket p = (L2GameClientPacket) GameServer.gameServer.getL2GamePacketHandler().handlePacket(bb, activeChar.getClient());
if (p != null)
{
p.setBuffers(bb, activeChar.getClient(), new NioNetStringBuffer(2000));
if (p.read())
{
ThreadPoolManager.getInstance().executePacket(p);
}
}
}
showValuesPage(activeChar, opCodes, format);
}
catch (Exception e)
{
e.printStackTrace();
showSendUsage(activeChar, null, null);
return false;
}
}
return true;
}
private boolean write(byte b, String string, ByteBuffer buf)
{
if ((b == 'C') || (b == 'c'))
{
buf.put(Byte.decode(string));
return true;
}
else if ((b == 'D') || (b == 'd'))
{
buf.putInt(Integer.decode(string));
return true;
}
else if ((b == 'H') || (b == 'h'))
{
buf.putShort(Short.decode(string));
return true;
}
else if ((b == 'F') || (b == 'f'))
{
buf.putDouble(Double.parseDouble(string));
return true;
}
else if ((b == 'S') || (b == 's'))
{
final int len = string.length();
for (int i = 0; i < len; i++)
{
buf.putChar(string.charAt(i));
}
buf.putChar('\000');
return true;
}
else if ((b == 'B') || (b == 'b') || (b == 'X') || (b == 'x'))
{
buf.put(new BigInteger(string).toByteArray());
return true;
}
else if ((b == 'Q') || (b == 'q'))
{
buf.putLong(Long.decode(string));
return true;
}
return false;
}
@Override
public String[] getAdminCommandList()
{
return ADMIN_COMMANDS;
}
}