Посмотрите видео ниже, чтобы узнать, как установить наш сайт в виде веб-приложения на главном экране.
Примечание: Эта функция может быть недоступна в некоторых браузерах.
/*
* Copyright (c) 2012-2015, RaveN Network INC. and/or its affiliates. All rights reserved.
* RAVEN NETWORK INC. PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* Licensed Materials - Property of RaveN Network INC.
* Restricted Rights - Use, duplication or disclosure restricted.
*/
package internal.generator;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
import javolution.util.FastMap;
import org.apache.commons.lang3.StringUtils;
import util.packet.CommonPacketSender;
import net.l2emuproject.proxy.network.game.client.L2GameClient;
import net.l2emuproject.proxy.network.game.server.L2GameServer;
import net.l2emuproject.proxy.network.meta.RandomAccessMMOBuffer;
import net.l2emuproject.proxy.network.meta.field.EnumeratedPayloadField;
import net.l2emuproject.proxy.script.ScriptFieldAlias;
import net.l2emuproject.proxy.script.game.InteractiveChatCommands;
import net.l2emuproject.proxy.script.game.PpeEnabledGameScript;
import net.l2emuproject.proxy.script.packets.InvalidPacketWriterArgumentsException;
import net.l2emuproject.proxy.state.entity.ObjectInfo;
import net.l2emuproject.proxy.state.entity.ObjectLocation;
import net.l2emuproject.proxy.state.entity.cache.ObjectInfoCache;
import net.l2emuproject.proxy.state.entity.context.ICacheServerID;
import net.l2emuproject.proxy.state.entity.type.NonPlayerControllable;
import net.l2emuproject.proxy.state.entity.type.ObjectType;
import net.l2emuproject.proxy.ui.savormix.io.base.IOConstants;
import net.l2emuproject.script.util.HasScriptDependencies;
import net.l2emuproject.util.L2Collections;
import net.l2emuproject.util.concurrent.L2ThreadPool;
import net.l2emuproject.util.logging.L2Logger;
/**
* A basic spawn list generator for non-moving NPCs.
* <B>The operator of this script must ensure</B> that the state is only saved after it was made sure
* that all NPC walkers that ever were in knownlist range have moved at least once (or have attacked
* something).
* However, alternative measures should be taken to ensure that stationary guards were not distracted
* by aggressive or negative reputation players.
*
* @author _dev_
*/
@HasScriptDependencies("util.packet.CommonPacketSender")
public class FixedSpawnGenerator extends PpeEnabledGameScript implements InteractiveChatCommands, IOConstants
{
static final L2Logger LOG = L2Logger.getLogger(FixedSpawnGenerator.class);
static final Pattern NAME_TRIM = Pattern.compile("(?:[0-9]+: )|(?:\\[not named in client\\])|(?: \\[NPC\\])");
@ScriptFieldAlias
private static final String NPC_OID = "fspawn_gen_npc_oid";
@ScriptFieldAlias
private static final String NPC_ATTACKABLE = "fspawn_gen_npc_atk";
@ScriptFieldAlias
private static final String WALKER_OID = "fspawn_walker_oid";
static final Path OUTPUT_ROOT = DATA_MINING_DIRECTORY.resolve("spawn_data");
//private final FastMap<ICacheServerID, ServerSpawns> _data;
// mapping by client results in better interactivity
private final FastMap<L2GameClient, ServerSpawns> _data;
private volatile Future<?> _saveTask;
/** Constructs this script. */
public FixedSpawnGenerator()
{
//_data = new FastMap<ICacheServerID, ServerSpawns>().setShared(true);
_data = new FastMap<L2GameClient, ServerSpawns>().setShared(true);
}
@Override
public void handleDisconnection(L2GameClient client)
{
_data.remove(client);
}
@Override
public void handleClientPacket(final L2GameClient client, L2GameServer server, RandomAccessMMOBuffer buf) throws RuntimeException
{
String msg = buf.readFirstString(CHAT_COMMAND);
if ("\\\\fs_reset".equals(msg))
{
_data.put(client, new ServerSpawns());
try
{
CommonPacketSender.sendChatMessage(client, 5, "SYS", "Spawn generator state cleared.");
}
catch (InvalidPacketWriterArgumentsException e)
{
LOG.warn("", e);
}
return;
}
if (!"\\\\fs_save".equals(msg))
return;
if (_saveTask != null && !_saveTask.isDone())
{
try
{
CommonPacketSender.sendChatMessage(client, 5, "SYS", "A state save is already in progress.");
}
catch (InvalidPacketWriterArgumentsException e)
{
LOG.warn("", e);
}
return;
}
final ICacheServerID context = getEntityContext(server);
//final ServerSpawns spawns = _data.get(context);
final ServerSpawns spawns = _data.get(client);
if (spawns == null)
return;
try
{
CommonPacketSender.sendChatMessage(client, 5, "SYS", "Saving " + spawns._fixedSpawns.size() + " static NPC spawns to disk.");
}
catch (InvalidPacketWriterArgumentsException e)
{
LOG.warn("", e);
// not a big deal if no message was sent; continue
}
_saveTask = L2ThreadPool.submitLongRunning(new Runnable()
{
@Override
public void run()
{
final Path dir = OUTPUT_ROOT.resolve(String.valueOf(client.getProtocol().getVersion()));
try
{
Files.createDirectories(dir);
try (final BufferedWriter bw = Files.newBufferedWriter(dir.resolve("walkers_" + System.currentTimeMillis() + ".txt"), Charset.forName("UTF-8")))
{
for (final Integer npc : spawns._walkerNPCs)
bw.append(String.valueOf(npc)).append("\r\n");
}
try (final BufferedWriter bw = Files.newBufferedWriter(dir.resolve("spawns_" + System.currentTimeMillis() + ".xml"), Charset.forName("UTF-8")))
{
bw.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append("\r\n\r\n");
bw.append("<list xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"../../templates/spawnlist.xsd\">");
bw.append("\r\n");
final Map<Integer, String> npcNames = new HashMap<>();
final Map<Integer, Set<ObjectLocation>> locByNPC = new TreeMap<>();
final ObjectInfoCache cache = ObjectInfoCache.getInstance();
for (final Entry<Integer, ObjectLocation> e : spawns._fixedSpawns.entrySet())
{
final ObjectInfo oi = cache.getOrAdd(e.getKey(), context);
final ObjectLocation initial = e.getValue(), current = oi.getLocation();
if (!initial.equals(current))
{
if (initial.getX() != current.getX() || initial.getY() != current.getY() || initial.getZ() != current.getZ())
{
LOG.info("OH NO IT'S A WALKER " + oi);
LOG.info("Current: " + current + ", old: " + initial);
}
else
LOG.info("Heading mismatch! Initial: " + initial.getHeading() + ", current: " + current.getHeading() + " for " + oi);
continue;
}
final ObjectType type = oi.getType();
if (!(type instanceof NonPlayerControllable))
{
LOG.info("OH NO IT'S NOT A NPC " + oi);
continue;
}
final Integer npc = ((NonPlayerControllable)type).getTemplateID();
if (spawns._walkerNPCs.contains(npc))
continue;
if (!npcNames.containsKey(npc))
npcNames.put(npc, NAME_TRIM.matcher(oi.toString()).replaceAll(""));
Set<ObjectLocation> locations = locByNPC.get(npc);
if (locations == null)
{
locations = new TreeSet<>(new LocationOrder());
locByNPC.put(npc, locations);
}
locations.add(initial);
}
for (final Entry<Integer, Set<ObjectLocation>> e : locByNPC.entrySet())
{
bw.append("\t<spawn npcId=\"").append(e.getKey().toString()).append("\">\r\n");
final String name = npcNames.get(e.getKey());
if (!StringUtils.isEmpty(name))
bw.append("\t\t<!-- ").append(name).append(" -->\r\n");
for (final ObjectLocation loc : e.getValue())
{
bw.append("\t\t<location x=\"").append(String.valueOf(loc.getX())).append("\" y=\"");
bw.append(String.valueOf(loc.getY())).append("\" z=\"").append(String.valueOf(loc.getZ()));
bw.append("\" heading=\"").append(String.valueOf(loc.getHeading())).append("\" />\r\n");
}
bw.append("\t</spawn>\r\n");
}
bw.append("</list>\r\n");
}
}
catch (IOException e)
{
LOG.error("Cannot save NPC spawns.", e);
return;
}
try
{
CommonPacketSender.sendChatMessage(client, 5, "SYS", "NPC spawns saved to disk.");
}
catch (InvalidPacketWriterArgumentsException e)
{
LOG.warn("", e);
// not a big deal if no message was sent
}
}
});
}
@Override
public void handleServerPacket(L2GameClient client, L2GameServer server, RandomAccessMMOBuffer buf) throws RuntimeException
{
removeWalker:
{
final EnumeratedPayloadField oid = buf.getSingleFieldIndex(WALKER_OID);
if (oid == null)
break removeWalker;
final ICacheServerID context = getEntityContext(server);
//ServerSpawns spawns = _data.get(context);
ServerSpawns spawns = _data.get(client);
if (spawns == null)
spawns = L2Collections.putIfAbsent(_data, client, new ServerSpawns());
// spawns = L2Collections.putIfAbsent(_data, context, new ServerSpawns());
final Integer objectID = buf.readInteger32(oid);
if (spawns._fixedSpawns.remove(objectID) == null)
return;
final ObjectInfo oi = ObjectInfoCache.getInstance().getOrAdd(objectID, context);
final ObjectType type = oi.getType();
if (!(type instanceof NonPlayerControllable))
return;
final NonPlayerControllable template = (NonPlayerControllable)type;
spawns._walkerNPCs.add(template.getTemplateID());
return;
}
addSpawn:
{
final EnumeratedPayloadField oid = buf.getSingleFieldIndex(NPC_OID);
final EnumeratedPayloadField atk = buf.getSingleFieldIndex(NPC_ATTACKABLE);
if (oid == null || atk == null)
break addSpawn;
final ICacheServerID context = getEntityContext(server);
//ServerSpawns spawns = _data.get(context);
ServerSpawns spawns = _data.get(client);
if (spawns == null)
spawns = L2Collections.putIfAbsent(_data, client, new ServerSpawns());
// spawns = L2Collections.putIfAbsent(_data, context, new ServerSpawns());
final Integer objectID = buf.readInteger32(oid);
final boolean hostile = buf.readInteger32(atk) != 0;
if (hostile || !spawns._ignoredOIDs.add(objectID))
return;
final ObjectInfo oi = ObjectInfoCache.getInstance().getOrAdd(objectID, context);
if (!(oi.getType() instanceof NonPlayerControllable))
return;
if (spawns._fixedSpawns.remove(objectID) != null)
{
LOG.info("Constraint violation for " + oi);
return;
}
spawns._fixedSpawns.put(objectID, oi.getLocation());
return;
}
}
@Override
public String getName()
{
return "NPC spawn gen (static)";
}
private static final class LocationOrder implements Comparator<ObjectLocation>
{
LocationOrder()
{
}
@Override
public int compare(ObjectLocation o1, ObjectLocation o2)
{
int diff = o1.getZ() - o2.getZ();
if (diff != 0)
return diff;
diff = o1.getY() - o2.getY();
if (diff != 0)
return diff;
diff = o1.getX() - o2.getX();
if (diff != 0)
return diff;
diff = o1.getHeading() - o2.getHeading();
if (diff != 0)
return diff;
return 0;
}
}
private static final class ServerSpawns
{
final Set<Integer> _ignoredOIDs;
final Map<Integer, ObjectLocation> _fixedSpawns;
final Set<Integer> _walkerNPCs;
ServerSpawns()
{
_fixedSpawns = new FastMap<Integer, ObjectLocation>().setShared(true);
_ignoredOIDs = new CopyOnWriteArraySet<Integer>();
_walkerNPCs = new CopyOnWriteArraySet<Integer>();
}
}
}
В классике структура пакетов немного другая )