Проверка Лицензии(Нужна помощь)

lxtopxm

Выдающийся
Местный
Сообщения
379
Розыгрыши
0
Репутация
239
Реакции
45
Баллы
1 375
Не знаю на скок правильно декомпилировании файл .

Помогите снять проверку лицензии. *


Java:
package atavism.server.plugins;

import atavism.agis.database.AccountDatabase;
import atavism.agis.database.ContentDatabase;
import atavism.agis.events.AbilityStatusEvent;
import atavism.agis.events.AbilityStatusMessage;
import atavism.agis.events.ConcludeQuest;
import atavism.agis.events.QuestResponse;
import atavism.agis.events.RequestQuestInfo;
import atavism.agis.plugins.AnimationClient;
import atavism.agis.plugins.ChatClient;
import atavism.agis.plugins.CombatClient;
import atavism.agis.plugins.DataLoggerClient;
import atavism.agis.plugins.QuestClient;
import atavism.agis.plugins.SocialClient;
import atavism.agis.plugins.ChatClient.TargetedComMessage;
import atavism.agis.plugins.QuestClient.QuestResponseMessage;
import atavism.agis.util.EventMessageHelper;
import atavism.agis.util.HelperFunctions;
import atavism.management.Management;
import atavism.msgsys.FilterUpdate;
import atavism.msgsys.Message;
import atavism.msgsys.MessageType;
import atavism.msgsys.MessageTypeFilter;
import atavism.msgsys.NoRecipientsException;
import atavism.msgsys.RPCTimeoutException;
import atavism.msgsys.SubjectMessage;
import atavism.msgsys.TargetMessage;
import atavism.server.engine.BasicWorldNode;
import atavism.server.engine.Database;
import atavism.server.engine.Engine;
import atavism.server.engine.EnginePlugin;
import atavism.server.engine.Event;
import atavism.server.engine.Namespace;
import atavism.server.engine.OID;
import atavism.server.events.ActivateItemEvent;
import atavism.server.events.AttachEvent;
import atavism.server.events.AuthorizedLoginEvent;
import atavism.server.events.AuthorizedLoginResponseEvent;
import atavism.server.events.AutoAttackEvent;
import atavism.server.events.ComEvent;
import atavism.server.events.CommandEvent;
import atavism.server.events.DirLocOrientEvent;
import atavism.server.events.ExtensionMessageEvent;
import atavism.server.events.FreeTerrainDecalEvent;
import atavism.server.events.LoadingStateEvent;
import atavism.server.events.LogoutEvent;
import atavism.server.events.ModelInfoEvent;
import atavism.server.events.NewLightEvent;
import atavism.server.events.NewTerrainDecalEvent;
import atavism.server.events.NotifyFreeObjectEvent;
import atavism.server.events.PlayerHaEvent;
import atavism.server.events.SceneLoadedEvent;
import atavism.server.events.WorldFileEvent;
import atavism.server.math.AOVector;
import atavism.server.math.Point;
import atavism.server.messages.LoginMessage;
import atavism.server.messages.LogoutMessage;
import atavism.server.messages.PerceptionFilter;
import atavism.server.messages.PerceptionTrigger;
import atavism.server.messages.PropertyMessage;
import atavism.server.messages.PerceptionMessage.ObjectNote;
import atavism.server.network.AOByteBuffer;
import atavism.server.network.ClientConnection;
import atavism.server.network.ClientTCPMessageIO;
import atavism.server.network.PacketAggregator;
import atavism.server.network.ClientConnection.AcceptCallback;
import atavism.server.network.rdp.RDPServer;
import atavism.server.network.rdp.RDPServerSocket;
import atavism.server.objects.DisplayContext;
import atavism.server.objects.InstanceEntryCallback;
import atavism.server.objects.InstanceRestorePoint;
import atavism.server.objects.InstanceTemplate;
import atavism.server.objects.Light;
import atavism.server.objects.LightData;
import atavism.server.objects.ObjectType;
import atavism.server.objects.ObjectTypes;
import atavism.server.objects.OceanData;
import atavism.server.objects.Player;
import atavism.server.objects.PlayerManager;
import atavism.server.objects.ProxyExtensionHook;
import atavism.server.objects.ProxyLoginCallback;
import atavism.server.objects.SoundData;
import atavism.server.objects.Template;
import atavism.server.objects.TerrainDecalData;
import atavism.server.objects.World;
import atavism.server.plugins.ClientParameter.ClientParameterMessage;
import atavism.server.plugins.InstanceClient.InstanceInfo;
import atavism.server.plugins.ProxyPlugin.1;
import atavism.server.plugins.ProxyPlugin.2;
import atavism.server.plugins.ProxyPlugin.3;
import atavism.server.plugins.WorldManagerClient.ExtensionMessage;
import atavism.server.plugins.WorldManagerClient.FreeRoadMessage;
import atavism.server.plugins.WorldManagerClient.MobPathMessage;
import atavism.server.plugins.WorldManagerClient.ObjectInfo;
import atavism.server.plugins.WorldManagerClient.PerceptionInfo;
import atavism.server.plugins.WorldManagerClient.SoundMessage;
import atavism.server.plugins.WorldManagerClient.TargetedExtensionMessage;
import atavism.server.telemetry.Prometheus;
import atavism.server.util.AOMeter;
import atavism.server.util.AORuntimeException;
import atavism.server.util.Base64;
import atavism.server.util.CountLogger;
import atavism.server.util.DebugUtils;
import atavism.server.util.EncryptionHelper;
import atavism.server.util.LockFactory;
import atavism.server.util.Log;
import atavism.server.util.Logger;
import atavism.server.util.ObjectLockManager;
import atavism.server.util.SQThreadPool;
import atavism.server.util.SecureToken;
import atavism.server.util.SecureTokenManager;
import atavism.server.util.ServerVersion;
import atavism.server.util.SquareQueue;
import atavism.server.util.TimeHistogram;
import atavism.server.util.CountLogger.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.Timer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

public class ProxyPlugin extends EnginePlugin implements AcceptCallback, atavism.server.network.ClientConnection.MessageCallback {
   private static int MESSAGE_QUEUE_THREADS = 16;
   private static int EVENT_QUEUE_THREADS = 16;
   private static int SLOW_EVENT_QUEUE_THREADS = 8;
   private static final int RDP_CHANNELS_COUNT = 128;
   public static final int PERCEPTION_GAIN_THRESHOLD = 20;
   CountLogger countLogger = new CountLogger("ProxyMsg", 5000, 2);
   Counter countMsgPerception;
   Counter countMsgPerceptionGain;
   Counter countMsgPerceptionLost;
   Counter countMsgUpdateWNodeIn;
   Counter countMsgUpdateWNodeOut;
   Counter countMsgPropertyIn;
   Counter countMsgPropertyOut;
   Counter countMsgTargetedProperty;
   Counter countMsgWNodeCorrectIn;
   Counter countMsgWNodeCorrectOut;
   Counter countMsgMobPathIn;
   Counter countMsgMobPathOut;
   public static boolean debugLic = false;
   protected Lock commandMapLock = LockFactory.makeLock("CommandMapLock");
   Map<String, atavism.server.plugins.ProxyPlugin.RegisteredCommand> commandMap = new HashMap();
   atavism.server.plugins.ProxyPlugin.CommandAccessCheck defaultCommandAccess = new atavism.server.plugins.ProxyPlugin.DefaultCommandAccess((1)null);
   SquareQueue<Player, Message> messageQQ = new SquareQueue("Message");
   SQThreadPool messageThreadPool = null;
   private final SquareQueue<Player, Event> eventQQ = new SquareQueue("Event");
   private SQThreadPool<Player, Event> eventThreadPool = null;
   private final SquareQueue<Player, Event> slowEventQQ = new SquareQueue("SlowEvent");
   private SQThreadPool<Player, Event> slowEventThreadPool = null;
   AOMeter clientMsgMeter = new AOMeter("ClientEventProcessorMeter");
   protected ConcurrentHashMap<OID, Long> playerLastClientTime = new ConcurrentHashMap();
   protected ConcurrentHashMap<OID, Long> playerLastServerTime = new ConcurrentHashMap();
   protected ConcurrentHashMap<OID, Long> playerFirstSpeedHackTime = new ConcurrentHashMap();
   protected ConcurrentHashMap<OID, Long> playerSpeedHackCount = new ConcurrentHashMap();
   public boolean defaultAllowClientToClientMessage = false;
   protected HashMap<String, MessageType> extensionMessageRegistry = new HashMap();
   private final ExecutorService logoutExecutor = Executors.newCachedThreadPool();
   protected AccountDatabase aDB;
   protected PerceptionFilter perceptionFilter;
   protected long perceptionSubId;
   protected PerceptionFilter responderFilter;
   protected PerceptionFilter responderFilter2;
   protected long responderSubId;
   protected long responderSubId2;
   protected int clientPort;
   protected static final Logger log = new Logger("ProxyPlugin");
   atavism.server.plugins.ProxyPlugin.PlayerMessageCallback playerMessageCallback = new atavism.server.plugins.ProxyPlugin.PlayerMessageCallback(this);
   protected PlayerManager playerManager = new PlayerManager();
   protected ConcurrentHashMap<OID, String> playersOnlineList = new ConcurrentHashMap();
   protected ConcurrentHashMap<OID, String> playersOnlineOnProxy = new ConcurrentHashMap();
   protected TimeHistogram proxyQueueHistogram = null;
   protected TimeHistogram proxyCallbackHistogram = null;
   protected List<MessageType> extraPlayerMessageTypes = null;
   private ProxyLoginCallback proxyLoginCallback = new atavism.server.plugins.ProxyPlugin.DefaultProxyLoginCallback((1)null);
   private InstanceEntryCallback instanceEntryCallback = new atavism.server.plugins.ProxyPlugin.DefaultInstanceEntryCallback((1)null);
   private int instanceEntryCount = 0;
   private int chatSentCount = 0;
   private int privateChatSentCount = 0;
   public static final MessageType MSG_TYPE_VOICE_PARMS = MessageType.intern("ao.VOICE_PARMS");
   public static final MessageType MSG_TYPE_PLAYER_PATH_REQ = MessageType.intern("ao.PLAYER_PATH_REQ");
   public static final MessageType MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST = MessageType.intern("ao.UPDATE_PLAYER_IGNORE_LIST");
   public static final MessageType MSG_TYPE_GET_MATCHING_PLAYERS = MessageType.intern("ao.GET_MATCHING_PLAYERS");
   public static final MessageType MSG_TYPE_PLAYER_IGNORE_LIST = MessageType.intern("ao.PLAYER_IGNORE_LIST");
   public static final MessageType MSG_TYPE_PLAYER_IGNORE_LIST_REQ = MessageType.intern("ao.PLAYER_IGNORE_LIST_REQ");
   public static final MessageType MSG_TYPE_RELAY_UPDATE_PLAYER_IGNORE_LIST = MessageType.intern("ao.RELAY_UPDATE_PLAYER_IGNORE_LIST");
   public static final MessageType MSG_TYPE_GET_PLAYER_LOGIN_STATUS = MessageType.intern("ao.GET_PLAYER_LOGIN_STATUS");
   public static final MessageType MSG_TYPE_LOGOUT_PLAYER = MessageType.intern("ao.LOGOUT_PLAYER");
   public static final MessageType MSG_TYPE_ADD_STATIC_PERCEPTION = MessageType.intern("ao.ADD_STATIC_PERCEPTION");
   public static final MessageType MSG_TYPE_REMOVE_STATIC_PERCEPTION = MessageType.intern("ao.REMOVE_STATIC_PERCEPTION");
   public static final MessageType MSG_TYPE_LOGIN_SPAWNED = MessageType.intern("ao.LOGIN_SPAWNED");
   public static final MessageType MSG_TYPE_ACCOUNT_LOGIN = MessageType.intern("ao.ACCOUNT_LOGIN");
   public static final MessageType MSG_TYPE_SERVER_SHUTDOWN_MESSAGE = MessageType.intern("server.Shutdown_Message");
   public static final MessageType MSG_TYPE_SERVER_SHUTDOWN = MessageType.intern("server.Shutdown");
   public static final MessageType MSG_TYPE_SERVER_RELOAD = MessageType.intern("server.Reload");
   protected static String voiceServerHost = "";
   protected static Integer voiceServerPort = null;
   public String serverCapabilitiesSentToClient = "DirLocOrient";
   public static int DiffTimeToSkipDirLocOrientMessage = 500;
   static int serverSocketReceiveBufferSize = 8388608;
   public static int MaxConcurrentUsers = 2000;
   public static int restriction_level = 0;
   public static int idleTimeout = 900;
   public static int silenceTimeout = 30;
   public static int silenceLoadingTimeout = 900;
   public static int maxMessagesBeforeConnectionReset = 2000;
   public static int maxByteCountBeforeConnectionReset = 1000000;
   public String capacityError = "Login Failed: Servers at capacity, please try again later.";
   public String tokenError = "Login Failed: Secure token invalid.";
   public static String SpeedhackChatMsg = "Detected Speedhack";
   public static int SpeedhackCountToDisconect = 10;
   public static int SpeedhackMinDiff = 8000;
   private ClientTCPMessageIO clientTCPMessageIO = null;
   Set<OID> adminSet = new HashSet();
   Map<OID, ClientConnection> clientConnections = new ConcurrentHashMap();
   Set<String> filteredProps = null;
   Set<String> playerSpecificProps = null;
   Set<String> cachedPlayerSpecificFilterProps = null;
   String serverVersion = null;
   protected Map<String, List<ProxyExtensionHook>> extensionHooks = new HashMap();
   private int connectionLimit = 0;
   boolean devMode = true;

   public ProxyPlugin() {
      super(getPluginName(), (atavism.msgsys.MessageCallback)null);
      this.setPluginType("Proxy");
      this.serverVersion = "10.7.0 " + ServerVersion.getBuildNumber();
      String MessageQueueThreadPoolSize = Engine.properties.getProperty("atavism.proxy.MessageQueueThreadPoolSize");
      if (MessageQueueThreadPoolSize != null) {
         try {
            int v = Integer.parseInt(MessageQueueThreadPoolSize);
            MESSAGE_QUEUE_THREADS = v;
         } catch (NumberFormatException var8) {
            var8.printStackTrace();
            Log.exception(var8);
         }
      }

      String EventQueueThreadPoolSize = Engine.properties.getProperty("atavism.proxy.EventQueueThreadPoolSize");
      if (EventQueueThreadPoolSize != null) {
         try {
            int v = Integer.parseInt(EventQueueThreadPoolSize);
            EVENT_QUEUE_THREADS = v;
         } catch (NumberFormatException var7) {
            var7.printStackTrace();
            Log.exception(var7);
         }
      }

      String proxy_concurrent_logins = Engine.properties.getProperty("atavism.proxy.ConcurrentLogins");
      if (proxy_concurrent_logins != null) {
         try {
            int v = Integer.parseInt(proxy_concurrent_logins);
            SLOW_EVENT_QUEUE_THREADS = v;
         } catch (NumberFormatException var6) {
            var6.printStackTrace();
            Log.exception(var6);
         }
      }

      this.messageThreadPool = new SQThreadPool(this.messageQQ, new atavism.server.plugins.ProxyPlugin.MessageCallback(this, this), MESSAGE_QUEUE_THREADS);
      this.eventThreadPool = new SQThreadPool(this.eventQQ, new atavism.server.plugins.ProxyPlugin.EventCallback(this), EVENT_QUEUE_THREADS);
      this.slowEventThreadPool = new SQThreadPool(this.slowEventQQ, new atavism.server.plugins.ProxyPlugin.EventCallback(this), SLOW_EVENT_QUEUE_THREADS);
      this.countMsgPerception = this.countLogger.addCounter("ao.PERCEPTION_INFO");
      this.countMsgPerceptionGain = this.countLogger.addCounter("Perception.gain");
      this.countMsgPerceptionLost = this.countLogger.addCounter("Perception.lost");
      this.countMsgUpdateWNodeIn = this.countLogger.addCounter("ao.UPDATEWNODE.in");
      this.countMsgUpdateWNodeOut = this.countLogger.addCounter("ao.UPDATEWNODE.out");
      this.countMsgPropertyIn = this.countLogger.addCounter("ao.PROPERTY.in");
      this.countMsgPropertyOut = this.countLogger.addCounter("ao.PROPERTY.out");
      this.countMsgTargetedProperty = this.countLogger.addCounter("ao.TARGETED_PROPERTY");
      this.countMsgWNodeCorrectIn = this.countLogger.addCounter("ao.WNODECORRECT.in");
      this.countMsgWNodeCorrectOut = this.countLogger.addCounter("ao.WNODECORRECT.out");
      this.countMsgMobPathIn = this.countLogger.addCounter("ao.MOB_PATH.in");
      this.countMsgMobPathOut = this.countLogger.addCounter("ao.MOB_PATH.out");
      ContentDatabase ctDB = new ContentDatabase(false);
      String _silenceTimeout = ctDB.loadGameSetting("PLAYER_SILENCE_TIMEOUT");
      if (_silenceTimeout != null) {
         silenceTimeout = Integer.parseInt(_silenceTimeout);
      }

      this.aDB = new AccountDatabase(true);
      this.addProxyExtensionHook("ao.heartbeat", new atavism.server.plugins.ProxyPlugin.PlayerHeartbeat((1)null));
      (new Thread(new atavism.server.plugins.ProxyPlugin.PlayerTimeout(this, (1)null), "PlayerTimeout")).start();
   }

   private static String getPluginName() {
      try {
         String proxyPluginName = Engine.getAgent().getDomainClient().allocName("PLUGIN", "Proxy#");
         return proxyPluginName;
      } catch (IOException var2) {
         throw new AORuntimeException("Could not allocate proxy plugin name", var2);
      }
   }

   public static boolean isOnBlockList(OID subject, OID target) {
      ExtensionMessage message = new ExtensionMessage(SocialClient.MSG_TYPE_IS_ON_BLOCK_LIST, "ao.IS_ON_BLOCK_LIST", subject);
      message.setProperty("targetOid", target);
      return Engine.getAgent().sendRPCReturnBoolean(message);
   }

   public boolean isDevMode() {
      return this.devMode;
   }

   public void setDevMode(boolean mode) {
      this.devMode = mode;
   }

   public List<MessageType> getExtraPlayerMessageTypes() {
      return this.extraPlayerMessageTypes;
   }

   public void setExtraPlayerMessageTypes(List<MessageType> extraPlayerMessageTypes) {
      this.extraPlayerMessageTypes = extraPlayerMessageTypes;
   }

   public void addExtraPlayerMessageType(MessageType messageType) {
      if (this.extraPlayerMessageTypes == null) {
         this.extraPlayerMessageTypes = new LinkedList();
      }

      this.extraPlayerMessageTypes.add(messageType);
   }

   public void addExtraPlayerExtensionMessageType(MessageType messageType) {
      this.addExtraPlayerMessageType(messageType);
      this.getHookManager().addHook(messageType, new atavism.server.plugins.ProxyPlugin.ExtensionHook(this));
   }

   public void addProxyExtensionHook(String subType, ProxyExtensionHook hook) {
      synchronized(this.extensionHooks) {
         List<ProxyExtensionHook> hookList = (List)this.extensionHooks.get(subType);
         if (hookList == null) {
            hookList = new ArrayList();
            this.extensionHooks.put(subType, hookList);
         }

         ((List)hookList).add(hook);
      }
   }

   public Map<String, List<ProxyExtensionHook>> getProxyExtensionHooks(String subType) {
      return this.extensionHooks;
   }

   public void onActivate() {
      try {
         PacketAggregator.initializeAggregation(Engine.getProperties());
         String logProxyHistograms = Engine.properties.getProperty("atavism.log_proxy_histograms");
         if (logProxyHistograms != null && logProxyHistograms.equals("true")) {
            int interval = 5000;
            String intervalString = Engine.properties.getProperty("atavism.log_proxy_histograms_interval");
            if (intervalString != null) {
               int newInterval = Integer.parseInt(intervalString);
               if (newInterval > 0) {
                  interval = newInterval;
               }
            }

            this.proxyQueueHistogram = new TimeHistogram("TimeInQ", interval);
            this.proxyCallbackHistogram = new TimeHistogram("TimeInCallback", interval);
            this.countLogger.start();
         }

         this.filteredProps = new HashSet();
         this.playerSpecificProps = new HashSet();
         this.cachedPlayerSpecificFilterProps = new HashSet();
         this.addFilteredProperty("inv.bag");
         this.addFilteredProperty(":loc");
         this.addFilteredProperty("masterOid");
         this.addFilteredProperty("agisobj.basedc");
         this.addFilteredProperty("aoobj.dc");
         this.addFilteredProperty("aoobj.followsterrainflag");
         this.addFilteredProperty("aoobj.perceiver");
         this.addFilteredProperty("aoobj.scale");
         this.addFilteredProperty("aoobj.mobflag");
         this.addFilteredProperty("aoobj.structflag");
         this.addFilteredProperty("aoobj.userflag");
         this.addFilteredProperty("aoobj.itemflag");
         this.addFilteredProperty("aoobj.lightflag");
         this.addFilteredProperty("namespace");
         this.addFilteredProperty("regenEffectMap");
         this.addFilteredProperty(WorldManagerClient.MOB_PATH_PROPERTY);
         this.addFilteredProperty(WorldManagerClient.TEMPL_SOUND_DATA_LIST);
         this.addFilteredProperty(WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
         this.addFilteredProperty("instanceStack");
         this.addFilteredProperty("currentInstanceName");
         this.addFilteredProperty("ignored_oids");
         this.registerHooks();
         atavism.server.plugins.ProxyPlugin.PluginMessageCallback pluginMessageCallback = new atavism.server.plugins.ProxyPlugin.PluginMessageCallback(this);
         MessageTypeFilter filter = new MessageTypeFilter();
         filter.addType(WorldManagerClient.MSG_TYPE_SYS_CHAT);
         Engine.getAgent().createSubscription(filter, pluginMessageCallback);
         LinkedList<MessageType> types = new LinkedList();
         types.add(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO);
         types.add(WorldManagerClient.MSG_TYPE_ANIMATION);
         types.add(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT);
         types.add(WorldManagerClient.MSG_TYPE_DETACH);
         types.add(PropertyMessage.MSG_TYPE_PROPERTY);
         types.add(ChatClient.MSG_TYPE_COM);
         types.add(SocialClient.MSG_TYPE_BLOCK_LIST);
         types.add(CombatClient.MSG_TYPE_DAMAGE);
         types.add(WorldManagerClient.MSG_TYPE_UPDATEWNODE);
         types.add(WorldManagerClient.MSG_TYPE_MOB_PATH);
         types.add(WorldManagerClient.MSG_TYPE_WNODECORRECT);
         types.add(WorldManagerClient.MSG_TYPE_ORIENT);
         types.add(WorldManagerClient.MSG_TYPE_SOUND);
         types.add(AnimationClient.MSG_TYPE_INVOKE_EFFECT);
         types.add(WorldManagerClient.MSG_TYPE_EXTENSION);
         types.add(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
         types.add(InventoryClient.MSG_TYPE_INV_UPDATE);
         types.add(CombatClient.MSG_TYPE_ABILITY_STATUS);
         types.add(CombatClient.MSG_TYPE_ABILITY_UPDATE);
         types.add(WorldManagerClient.MSG_TYPE_FOG);
         types.add(WorldManagerClient.MSG_TYPE_ROAD);
         types.add(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT);
         types.add(WorldManagerClient.MSG_TYPE_SET_AMBIENT);
         types.add(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY);
         types.add(WorldManagerClient.MSG_TYPE_FREE_OBJECT);
         types.add(MSG_TYPE_VOICE_PARMS);
         types.add(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
         types.add(MSG_TYPE_GET_MATCHING_PLAYERS);
         types.add(MSG_TYPE_ADD_STATIC_PERCEPTION);
         types.add(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
         if (this.extraPlayerMessageTypes != null) {
            types.addAll(this.extraPlayerMessageTypes);
         }

         this.perceptionFilter = new PerceptionFilter(types, true);
         PerceptionTrigger perceptionTrigger = new PerceptionTrigger();
         this.perceptionSubId = Engine.getAgent().createSubscription(this.perceptionFilter, this.playerMessageCallback, 0, perceptionTrigger);
         types.clear();
         types.add(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ);
         types.add(MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
         types.add(MSG_TYPE_GET_PLAYER_LOGIN_STATUS);
         types.add(MSG_TYPE_LOGOUT_PLAYER);
         this.responderFilter = new PerceptionFilter(types);
         this.responderSubId = Engine.getAgent().createSubscription(this.responderFilter, this.playerMessageCallback, 8);
         this.responderFilter2 = new PerceptionFilter();
         this.responderSubId2 = Engine.getAgent().createSubscription(this.responderFilter2, this, 8);
         types.clear();
         types.add(Management.MSG_TYPE_GET_PLUGIN_STATUS);
         Engine.getAgent().createSubscription(new MessageTypeFilter(types), pluginMessageCallback, 8);
         MessageTypeFilter filter3 = new MessageTypeFilter();
         filter3.addType(MSG_TYPE_ACCOUNT_LOGIN);
         Engine.getAgent().createSubscription(filter3, this);
         String log_rdp_counters = Engine.getProperty("atavism.log_rdp_counters");
         if (log_rdp_counters == null || log_rdp_counters.equals("false")) {
            RDPServer.setCounterLogging(false);
         }

         RDPServer.startRDPServer();
         this.initializeVoiceServerInformation();
         this.registerExtensionSubtype("voice_parms", MSG_TYPE_VOICE_PARMS);
         this.registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
         this.registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
         this.registerExtensionSubtype("ao.UPDATE_PLAYER_IGNORE_LIST", MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
         this.registerExtensionSubtype("ao.GET_MATCHING_PLAYERS", MSG_TYPE_GET_MATCHING_PLAYERS);
         this.registerExtensionSubtype("ao.PLAYER_IGNORE_LIST_REQ", MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
         Log.debug("ProxyPlugin before bindAddress");
         InetSocketAddress bindAddress = this.getBindAddress();
         Log.debug("ProxyPlugin after bindAddress " + bindAddress.getHostName() + " " + bindAddress.getAddress() + " " + bindAddress.getPort());
         Log.debug("ProxyPlugin before server socket");
         int port = Integer.parseInt(Engine.getProperty("atavism.proxy.bindport").trim());
         Log.debug("Proxy: getBindAddress port=" + port);
         String agent_name = Engine.getAgent().getName();
         String[] an = agent_name.split("_");
         int agentId = Integer.parseInt(an[1]);
         port += agentId - 1;
         int rdpChannels = Integer.parseInt(Engine.properties.getProperty("atavism.proxy.rdp_channels", String.valueOf(128)));

         for(int i = 0; i < rdpChannels; ++i) {
            RDPServerSocket serverSocket = new RDPServerSocket();
            serverSocket.registerAcceptCallback(this);
            serverSocket.bind(port, serverSocketReceiveBufferSize);
            if (Log.loggingDebug) {
               Log.debug("BIND: binding for client tcp and rdp packets on port " + bindAddress.getPort() + " with rdpsocket: " + serverSocket.toString());
            }
         }

         Log.debug("BIND: bound server socket");
         this.clientTCPMessageIO = ClientTCPMessageIO.setup(bindAddress, this, this);
         Log.debug("BIND: setup clientTCPMessage");
         this.clientTCPMessageIO.start("ClientIO");
         Log.debug("BIND: started clientTCPMessage");
         InetSocketAddress externalAddress = this.getExternalAddress(bindAddress);
         Log.debug("BIND: got external Address " + externalAddress.getHostName() + " " + externalAddress.getAddress() + " " + externalAddress.getPort());
         this.setPluginInfo("host=" + Engine.getProperty("atavism.proxy.externaladdress") + ",port=" + externalAddress.getPort());
         Log.debug("Registering proxy plugin");
         Engine.registerStatusReportingPlugin(this);
         Log.debug("Proxy: activation done");
         this.runCheck();
         Gauge.builder("event_qq_size", new 1(this)).register(Prometheus.registry());
         Gauge.builder("message_qq_size", new 2(this)).register(Prometheus.registry());
         Gauge.builder("message_qq_unqueued_size", new 3(this)).register(Prometheus.registry());
      } catch (Exception var16) {
         throw new AORuntimeException("activate failed", var16);
      }
   }

   private InetSocketAddress getBindAddress() throws IOException {
      String propStr = Engine.getProperty("atavism.proxy.bindport");
      Log.debug("Proxy: getBindAddress propStr=" + propStr);
      int port;
      if (propStr != null) {
         port = Integer.parseInt(propStr.trim());
         Log.debug("Proxy: getBindAddress port=" + port);
         String agent_name = Engine.getAgent().getName();
         String[] an = agent_name.split("_");
         int agentId = Integer.parseInt(an[1]);
         port += agentId - 1;
         Log.debug("Proxy: getBindAddress port=" + port);
      } else {
         port = Integer.parseInt(Engine.getProperty("atavism.proxyport").trim());
      }

      Log.debug("Proxy: getBindAddress port=" + port);
      propStr = Engine.getProperty("atavism.proxy.bindaddress");
      Log.debug("Proxy: getBindAddress propStr=" + propStr + " " + Character.digit(propStr.charAt(0), 16) + " " + Character.digit(propStr.charAt(1), 16) + " " + Character.digit(propStr.charAt(2), 16) + " c=");
      int count = 0;
      if (propStr.contains(".")) {
         for(int i = 0; i < propStr.length(); ++i) {
            if (propStr.charAt(i) == '.') {
               ++count;
            }
         }
      }

      InetAddress address = null;
      InetAddress[] address2 = null;
      if (count == 3 && Character.digit(propStr.charAt(0), 10) != -1) {
      }

      if (propStr != null) {
         try {
            address = InetAddress.getByName(propStr.trim());
            address2 = InetAddress.getAllByName(propStr.trim());
            InetAddress[] var6 = address2;
            int var7 = address2.length;

            for(int var8 = 0; var8 < var7; ++var8) {
               InetAddress ai = var6[var8];
               Log.debug("Proxy: getBindAddress address2=" + ai + " " + ai.getHostName() + " " + ai.getHostAddress());
            }

            Log.debug("Proxy: getBindAddress address=" + address + " " + address.getHostName() + " " + address.getHostAddress());
         } catch (UnknownHostException var10) {
            log.error("getBindAddress " + var10.getMessage() + " " + var10.getLocalizedMessage());
         }
      }

      Log.debug("Proxy: getBindAddress address=" + address + " " + address.getHostName() + " " + address.getAddress());
      return new InetSocketAddress(address, port);
   }

   private InetSocketAddress getExternalAddress(InetSocketAddress bindAddress) throws IOException {
      String propStr = Engine.getProperty("atavism.proxy.externalport");
      Log.debug("Proxy: getExternalAddress ext port propStr=" + propStr);
      int port;
      if (propStr != null) {
         port = Integer.parseInt(propStr.trim());
      } else {
         port = bindAddress.getPort();
      }

      Log.debug("Proxy: getExternalAddress port=" + port);
      propStr = Engine.getProperty("atavism.proxy.externaladdress");
      Log.debug("Proxy: getExternalAddress ext addr propStr=" + propStr);
      InetAddress address;
      if (propStr != null) {
         address = InetAddress.getByName(propStr.trim());
      } else {
         address = bindAddress.getAddress();
         Log.debug("Proxy: getExternalAddress else address=" + address);
         if (address.isAnyLocalAddress()) {
            address = InetAddress.getLocalHost();
            Log.debug("Proxy: getExternalAddress get local host address=" + address + " " + address.getHostName() + " " + address.getHostAddress());
         }
      }

      Log.debug("Proxy: getExternalAddress address=" + address + " " + address.getHostName() + " " + address.getAddress());
      return new InetSocketAddress(address, port);
   }

   private String howla() {
      String characters = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnoprstquwxyz123456789";
      String k = "";

      for(int i = 0; i < 14; ++i) {
         Random random = new Random();
         k = k + characters.charAt(random.nextInt(characters.length() - 1));
      }

      return k;
   }

   private void runCheck() {
      String email = Engine.getProperty("atavism.licence.email");
      String licencekey = Engine.getProperty("atavism.licence.key");
      String proxy_id = Engine.getProperty("atavism.proxy.id");
      int num = 0;
      int proxyId = 0;

      try {
         if (proxy_id != null && proxy_id != "") {
            proxyId = Integer.parseInt(proxy_id);
         }
      } catch (NumberFormatException var18) {
      }

      String[] url = new String[]{"https://apanel.atavismonline.com/login/verifyserver.php", "https://licensing2.dragonsan.com:2443/login/verifyserver.php", "https://licensing1.atavismonline.com/login/verifyserver.php", "https://licensing.dragonsan.com/login/verifyserver.php", "https://licensing1.dragonsan.com/login/verifyserver.php", "https://licensing.atavismonline.com/login/verifyserver.php", "https://licensing2.atavismonline.com/login/verifyserver.php"};
      String resSor = this.howla();
      atavism.server.plugins.ProxyPlugin.rck reCheck = new atavism.server.plugins.ProxyPlugin.rck(this, resSor);
      Engine.getExecutor().scheduleAtFixedRate(reCheck, 300L, 300L, TimeUnit.SECONDS);

      while(num < url.length) {
         boolean failed = false;

         try {
            String res = "";
            URL urlObj = new URL(url[num]);
            URLConnection lu = urlObj.openConnection();
            lu.setConnectTimeout(10000);
            String data = "email=" + URLEncoder.encode(email, "UTF-8") + "&licence=" + URLEncoder.encode(licencekey, "UTF-8") + "&ver=" + URLEncoder.encode("10.7.0", "UTF-8") + "&addr=" + URLEncoder.encode(Engine.getProperty("atavism.proxy.bindaddress"), "UTF-8") + "&sor=" + URLEncoder.encode(resSor, "UTF-8") + "&c=" + URLEncoder.encode("0", "UTF-8") + "&cp=" + this.playerManager.getPlayerCount() + " &pi=" + proxyId + "&build=" + URLEncoder.encode(ServerVersion.getBuildDate(), "UTF-8") + "&m=" + MaxConcurrentUsers;
            lu.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(lu.getOutputStream());
            wr.write(data);
            wr.flush();
            BufferedReader rd = new BufferedReader(new InputStreamReader(lu.getInputStream()));

            for(String line = ""; (line = rd.readLine()) != null; res = res + line) {
            }

            wr.flush();
            wr.close();
            if (debugLic) {
               System.out.println("\n" + url[num] + "\n" + res + "\n");
            }

            res = HelperFunctions.readEncodedString(Base64.decode(res));
            String[] output = res.split(":");
            if (debugLic) {
               System.out.println("\nsec: " + resSor + "\n s: " + HelperFunctions.readEncodedString(Base64.decode(output[2])) + "\n");
            }

            if (EncryptionHelper.passwordMD5Check(output[0], this.getTemp()) && resSor.equals(HelperFunctions.readEncodedString(Base64.decode(output[2])))) {
               this.connectionLimit = Integer.parseInt(HelperFunctions.readEncodedString(Base64.decode(output[1])));
            } else {
               System.out.println("\nLicense verification failed");
               Log.error("License verification failed");
            }

            Log.debug("CONNECTOR: connections set to: " + this.connectionLimit);
         } catch (Exception var19) {
            Log.error("CONNECTOR: failed verifying " + var19);
            if (debugLic) {
               System.out.println("\n" + url[num] + "\n" + var19);
            }

            ++num;
            failed = true;
         }

         if (!failed) {
            return;
         }
      }

      System.out.println("\nLicense verification failed");
      Log.error("License verification failed");
      this.connectionLimit = 0;
   }

   public Map<String, String> getStatusMap() {
      Map<String, String> status = new HashMap();
      status.put("players", Integer.toString(this.playerManager.getPlayerCount()));
      return status;
   }

   public void registerCommand(String command, atavism.server.plugins.ProxyPlugin.CommandParser parser) {
      this.commandMapLock.lock();

      try {
         this.commandMap.put(command, new atavism.server.plugins.ProxyPlugin.RegisteredCommand(parser, this.defaultCommandAccess));
      } finally {
         this.commandMapLock.unlock();
      }

   }

   public void registerCommand(String command, atavism.server.plugins.ProxyPlugin.CommandParser parser, atavism.server.plugins.ProxyPlugin.CommandAccessCheck access) {
      this.commandMapLock.lock();

      try {
         this.commandMap.put(command, new atavism.server.plugins.ProxyPlugin.RegisteredCommand(parser, access));
      } finally {
         this.commandMapLock.unlock();
      }

   }

   void registerHooks() {
      log.debug("registering hooks");
      this.getHookManager().addHook(SocialClient.MSG_TYPE_BLOCK_LIST, new atavism.server.plugins.ProxyPlugin.BlockListHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT, new atavism.server.plugins.ProxyPlugin.DisplayContextHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_DETACH, new atavism.server.plugins.ProxyPlugin.DetachHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_ANIMATION, new atavism.server.plugins.ProxyPlugin.AnimationHook(this));
      this.getHookManager().addHook(AnimationClient.MSG_TYPE_INVOKE_EFFECT, new atavism.server.plugins.ProxyPlugin.InvokeEffectHook(this));
      this.getHookManager().addHook(PropertyMessage.MSG_TYPE_PROPERTY, new atavism.server.plugins.ProxyPlugin.PropertyHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_EXTENSION, new atavism.server.plugins.ProxyPlugin.ExtensionHook(this));
      this.getHookManager().addHook(CombatClient.MSG_TYPE_ABILITY_STATUS, new atavism.server.plugins.ProxyPlugin.AbilityStatusHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY, new atavism.server.plugins.ProxyPlugin.TargetedPropertyHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO, new atavism.server.plugins.ProxyPlugin.PerceptionHook(this));
      this.getHookManager().addHook(ChatClient.MSG_TYPE_COM, new atavism.server.plugins.ProxyPlugin.ComHook(this));
      this.getHookManager().addHook(CombatClient.MSG_TYPE_DAMAGE, new atavism.server.plugins.ProxyPlugin.DamageHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_SYS_CHAT, new atavism.server.plugins.ProxyPlugin.SysChatHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_UPDATEWNODE, new atavism.server.plugins.ProxyPlugin.UpdateWNodeHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_MOB_PATH, new atavism.server.plugins.ProxyPlugin.UpdateMobPathHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_WNODECORRECT, new atavism.server.plugins.ProxyPlugin.WNodeCorrectHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_ORIENT, new atavism.server.plugins.ProxyPlugin.OrientHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_SOUND, new atavism.server.plugins.ProxyPlugin.SoundHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_FOG, new atavism.server.plugins.ProxyPlugin.FogHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_ROAD, new atavism.server.plugins.ProxyPlugin.RoadHook(this));
      this.getHookManager().addHook(InventoryClient.MSG_TYPE_INV_UPDATE, new atavism.server.plugins.ProxyPlugin.InvUpdateHook(this));
      this.getHookManager().addHook(CombatClient.MSG_TYPE_ABILITY_UPDATE, new atavism.server.plugins.ProxyPlugin.AbilityUpdateHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT, new atavism.server.plugins.ProxyPlugin.NewDirLightHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_FREE_OBJECT, new atavism.server.plugins.ProxyPlugin.FreeObjectHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_SET_AMBIENT, new atavism.server.plugins.ProxyPlugin.SetAmbientHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_P2P_EXTENSION, new atavism.server.plugins.ProxyPlugin.P2PExtensionHook(this));
      this.getHookManager().addHook(MSG_TYPE_VOICE_PARMS, new atavism.server.plugins.ProxyPlugin.VoiceParmsHook(this));
      this.getHookManager().addHook(MSG_TYPE_PLAYER_PATH_REQ, new atavism.server.plugins.ProxyPlugin.PlayerPathReqHook(this));
      this.getHookManager().addHook(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ, new atavism.server.plugins.ProxyPlugin.InstanceEntryReqHook(this));
      this.getHookManager().addHook(Management.MSG_TYPE_GET_PLUGIN_STATUS, new atavism.server.plugins.ProxyPlugin.GetPluginStatusHook(this));
      this.getHookManager().addHook(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST, new atavism.server.plugins.ProxyPlugin.UpdatePlayerIgnoreListHook(this));
      this.getHookManager().addHook(MSG_TYPE_GET_MATCHING_PLAYERS, new atavism.server.plugins.ProxyPlugin.GetMatchingPlayersHook(this));
      this.getHookManager().addHook(MSG_TYPE_PLAYER_IGNORE_LIST_REQ, new atavism.server.plugins.ProxyPlugin.PlayerIgnoreListReqHook(this));
      this.getHookManager().addHook(MSG_TYPE_GET_PLAYER_LOGIN_STATUS, new atavism.server.plugins.ProxyPlugin.GetPlayerLoginStatusHook(this, (1)null));
      this.getHookManager().addHook(MSG_TYPE_LOGOUT_PLAYER, new atavism.server.plugins.ProxyPlugin.LogoutPlayerHook(this, (1)null));
      this.getHookManager().addHook(MSG_TYPE_ADD_STATIC_PERCEPTION, new atavism.server.plugins.ProxyPlugin.AddStaticPerceptionHook(this, (1)null));
      this.getHookManager().addHook(MSG_TYPE_REMOVE_STATIC_PERCEPTION, new atavism.server.plugins.ProxyPlugin.RemoveStaticPerceptionHook(this, (1)null));
      this.getHookManager().addHook(MSG_TYPE_ACCOUNT_LOGIN, new atavism.server.plugins.ProxyPlugin.AccountLoginHook(this, (1)null));
   }

   void callEngineOnMessage(Message message, int flags) {
      super.handleMessage(message, flags);
   }

   protected void initializeVoiceServerInformation() {
      voiceServerHost = Engine.properties.getProperty("atavism.voiceserver");
      String s = Engine.properties.getProperty("atavism.voiceport");
      if (s != null) {
         voiceServerPort = Integer.parseInt(s);
      }

      if (Log.loggingDebug) {
         log.debug("initializeVoiceServerInformation: voiceServerHost " + voiceServerHost + ", voiceServerPort " + voiceServerPort);
      }

   }

   public void acceptConnection(ClientConnection con) {
      Log.info("ProxyPlugin: CONNECTION remote=" + con);
      con.registerMessageCallback(this);
   }

   public void processPacket(ClientConnection con, AOByteBuffer buf) {
      try {
         long time1 = System.nanoTime();
         if (Log.loggingNet) {
            if (ClientConnection.getLogMessageContents()) {
               Log.net("ProxyPlugin.processPacket: con " + con + ", length " + buf.limit() + ", packet " + DebugUtils.byteArrayToHexString(buf));
            } else {
               Log.net("ProxyPlugin.processPacket: con " + con + ", buf " + buf);
            }
         }

         Event event = Engine.getEventServer().parseBytes(buf, con);
         if (event == null) {
            Log.error("Engine: could not parse packet data, remote=" + con);
            return;
         }

         SquareQueue<Player, Event> qq = this.eventQQ;
         if (event instanceof AuthorizedLoginEvent) {
            qq = this.slowEventQQ;
         }

         Player player = (Player)con.getAssociation();
         if (player == null) {
            if (!(event instanceof AuthorizedLoginEvent)) {
               Log.error("Cannot process event for connection with no player: " + con);
               return;
            }

            Log.info("ProxyPlugin: LOGIN_RECV remote=" + con + " playerOid=" + ((AuthorizedLoginEvent)event).getOid());
            player = new Player(((AuthorizedLoginEvent)event).getOid(), con);
         }

         this.playerManager.processEvent(player, event, qq);
         long time2 = System.nanoTime();
         Timer.builder("process_packet_time").tags(new String[]{"event", event.getClass().getSimpleName()}).publishPercentiles(new double[]{0.9D}).register(Prometheus.registry()).record(Duration.ofNanos(time2 - time1));
      } catch (AORuntimeException var10) {
         Log.exception("ProxyPlugin.processPacket caught exception", var10);
      }

   }

   public Set<OID> getPlayerOids() {
      List<Player> players = new ArrayList(this.playerManager.getPlayerCount());
      this.playerManager.getPlayers(players);
      Set<OID> result = new HashSet(players.size());
      Iterator var3 = players.iterator();

      while(var3.hasNext()) {
         Player player = (Player)var3.next();
         result.add(player.getOid());
      }

      return result;
   }

   public List<String> getPlayerNames() {
      List<Player> players = new ArrayList(this.playerManager.getPlayerCount());
      Log.debug("ProxyPlugin.getPlayerNames: count is " + this.playerManager.getPlayerCount());
      this.playerManager.getPlayers(players);
      List<String> result = new ArrayList(players.size());
      Iterator var3 = players.iterator();

      while(var3.hasNext()) {
         Player player = (Player)var3.next();
         result.add(player.getName() + " " + player.getOid() + " " + this.getName());
      }

      Collections.sort(result);
      return result;
   }

   public List<String> getAllPlayerNames() {
      Log.debug("ProxyPlugin.getAllPlayerNames: count is " + this.playersOnlineList.size());
      List<String> result = new ArrayList(this.playersOnlineList.size());
      HashMap<OID, String> plays = new HashMap();
      plays.putAll(this.playersOnlineList);
      Iterator var3 = plays.keySet().iterator();

      while(var3.hasNext()) {
         OID player = (OID)var3.next();
         result.add((String)plays.get(player) + " " + player + " " + (String)this.playersOnlineOnProxy.get(player));
      }

      Collections.sort(result);
      return result;
   }

   public List<Player> getPlayers() {
      List<Player> players = new ArrayList(this.playerManager.getPlayerCount());
      this.playerManager.getPlayers(players);
      return players;
   }

   public Player getPlayer(OID oid) {
      return this.playerManager.getPlayer(oid);
   }

   public void addPlayerMessage(Message message, Player player) {
      long start = System.nanoTime();
      message.setEnqueueTime();
      this.messageQQ.insert(player, message);
      long microseconds = System.nanoTime() - start;
   }

   public void addFilteredProperty(String filteredProperty) {
      this.filteredProps.add(filteredProperty);
      this.cachedPlayerSpecificFilterProps.add(filteredProperty);
   }

   public void addPlayerSpecificProperty(String filteredProperty) {
      this.playerSpecificProps.add(filteredProperty);
      this.cachedPlayerSpecificFilterProps.add(filteredProperty);
   }

   protected void recreatePlayerSpecificCache() {
      this.cachedPlayerSpecificFilterProps = new HashSet();
      this.cachedPlayerSpecificFilterProps.addAll(this.filteredProps);
      this.cachedPlayerSpecificFilterProps.addAll(this.playerSpecificProps);
   }

   protected boolean processLogin(ClientConnection con, AuthorizedLoginEvent loginEvent) {
      Prometheus.registry().counter("player_login_request", new String[0]).increment();
      OID playerOid = loginEvent.getOid();
      String version = loginEvent.getVersion();
      int nPlayers = this.playerManager.getPlayerCount();
      String[] clientVersionCapabilities = null;
      if (version != null && version.length() > 0) {
         clientVersionCapabilities = version.split(",");
      }

      LinkedList<String> clientCapabilities = new LinkedList();
      String clientVersion = "";
      int i;
      if (clientVersionCapabilities != null && clientVersionCapabilities.length > 0) {
         clientVersion = clientVersionCapabilities[0];

         for(i = 1; i < clientVersionCapabilities.length; ++i) {
            clientCapabilities.add(clientVersionCapabilities[i].trim());
         }
      }

      i = ServerVersion.compareVersionStrings(clientVersion, "10.7.0");
      AuthorizedLoginResponseEvent loginResponse;
      if (i != 0) {
         Log.warn("processLogin: unsupported version " + clientVersion + " from player: " + playerOid);
         loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Unsupported client version", this.serverVersion);
         con.send(loginResponse.toBytes());
         Prometheus.registry().counter("player_login_result", new String[]{"status", "unsupported_version"}).increment();
         return false;
      } else {
         if (this.isAdmin(playerOid) && nPlayers < this.connectionLimit) {
            Log.debug("processLogin: player is admin, bypassing max check");
         } else {
            Log.debug("processLogin: player is not admin");
            if (nPlayers >= MaxConcurrentUsers || nPlayers >= this.connectionLimit) {
               Log.warn("processLogin: too many users, failed for player: " + playerOid);
               loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, this.capacityError, this.serverVersion);
               con.send(loginResponse.toBytes());
               Prometheus.registry().counter("player_login_result", new String[]{"status", "too_many_users_" + String.valueOf(this.connectionLimit)}).increment();
               return false;
            }
         }

         SecureToken token = SecureTokenManager.getInstance().importToken(loginEvent.getWorldToken());
         boolean validToken = true;
         if (!token.getValid()) {
            Log.debug("token is not valid");
            validToken = false;
         }

         OID characterOid = (OID)token.getProperty("character_oid");
         if (Log.loggingDebug) {
            Log.debug("PlayerOID: " + playerOid);
         }

         if (Log.loggingDebug) {
            Log.debug("CharacterOID: " + characterOid);
         }

         if (!playerOid.equals(characterOid)) {
            Log.debug("playerOid does not match character_oid");
            validToken = false;
         }

         if (!token.getProperty("proxy_server").equals(Engine.getAgent().getName())) {
            Log.debug("proxy_server does not match engine agent name");
            validToken = false;
         }

         if (!validToken) {
            Log.error("processLogin: invalid proxy token");
            Event loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, this.tokenError, this.serverVersion);
            con.send(loginResponse.toBytes());
            Prometheus.registry().counter("player_login_result", new String[]{"status", "invalid_token"}).increment();
            return false;
         } else {
            try {
               TargetMessage getPlayerLoginStatus = new TargetMessage(MSG_TYPE_GET_PLAYER_LOGIN_STATUS, playerOid);
               atavism.server.plugins.ProxyPlugin.PlayerLoginStatus loginStatus = (atavism.server.plugins.ProxyPlugin.PlayerLoginStatus)Engine.getAgent().sendRPCReturnObject(getPlayerLoginStatus);
               if (this.proxyLoginCallback.duplicateLogin(loginStatus, con)) {
                  if (loginStatus != null) {
                     if (Log.loggingInfo) {
                        Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " name=" + loginStatus.name + " existingCon=" + loginStatus.clientCon + " existingProxy=" + loginStatus.proxyPluginName);
                     }
                  } else if (Log.loggingInfo) {
                     Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " loginStatus is null");
                  }

                  log.debug("processLogin: Send logout");
                  Prometheus.registry().counter("player_logout", new String[]{"reason", "duplicate"}).increment();
                  TargetMessage logoutPly = new TargetMessage(MSG_TYPE_LOGOUT_PLAYER, playerOid);
                  Engine.getAgent().sendRPCReturnObject(logoutPly);
                  log.debug("processLogin: Send logout | ");
                  AuthorizedLoginResponseEvent loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Already connected", this.serverVersion);
                  con.send(loginResponse.toBytes());
                  Prometheus.registry().counter("player_login_result", new String[]{"status", "duplicate"}).increment();
                  return false;
               }
            } catch (NoRecipientsException var20) {
               if (Log.loggingDebug) {
                  log.debug("processLogin: OK! player is not logged " + var20);
               }
            }

            Player player = new Player(playerOid, con);
            player.setStatus(1);
            if (!this.playerManager.addPlayer(player)) {
               player = this.playerManager.getPlayer(playerOid);
               Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " existing=" + player.getConnection());
               AuthorizedLoginResponseEvent loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Already connected", this.serverVersion);
               con.send(loginResponse.toBytes());
               Prometheus.registry().counter("player_login_result", new String[]{"status", "duplicate_add"}).increment();
               return false;
            } else {
               con.setAssociation(player);
               player.setVersion(clientVersion);
               player.setCapabilities(clientCapabilities);
               String errorMessage = this.proxyLoginCallback.preLoad(player, con);
               AuthorizedLoginResponseEvent loginResponse;
               if (errorMessage != null) {
                  this.playerManager.removePlayer(playerOid);
                  loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, errorMessage, this.serverVersion);
                  con.send(loginResponse.toBytes());
                  Prometheus.registry().counter("player_login_result", new String[]{"status", "pre_load_error"}).increment();
                  return false;
               } else {
                  if (Log.loggingDebug) {
                     Log.debug("processLogin: loading object: " + playerOid + ", con=" + con);
                  }

                  if (!this.loadPlayerObject(player)) {
                     Log.error("processLogin: could not load object " + playerOid);
                     this.playerManager.removePlayer(playerOid);
                     loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed", this.serverVersion);
                     con.send(loginResponse.toBytes());
                     Prometheus.registry().counter("player_login_result", new String[]{"status", "not_loaded"}).increment();
                     return false;
                  } else {
                     if (Log.loggingDebug) {
                        Log.debug("processLogin: loaded player object: " + playerOid);
                     }

                     errorMessage = this.proxyLoginCallback.postLoad(player, con);
                     if (errorMessage != null) {
                        this.playerManager.removePlayer(playerOid);
                        loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, errorMessage, this.serverVersion);
                        con.send(loginResponse.toBytes());
                        Prometheus.registry().counter("player_login_result", new String[]{"status", "error"}).increment();
                        return false;
                     } else {
                        loginResponse = new AuthorizedLoginResponseEvent(playerOid, true, "Login Succeeded", this.serverVersion + ", " + this.serverCapabilitiesSentToClient);
                        con.send(loginResponse.toBytes());
                        if (Log.loggingDebug) {
                           Log.debug("Login response sent for playerOid=" + playerOid + " the authorized login response message is : " + loginResponse.getMessage());
                        }

                        this.playerManager.addStaticPerception(player, playerOid);
                        boolean loginOK = this.processLoginHelper(con, player);
                        if (Log.loggingDebug) {
                           log.debug("processLogin: loginOK?:" + loginOK + "  | player=" + player);
                        }

                        if (!loginOK) {
                           if (Log.loggingDebug) {
                              Log.debug("processLogin: loading object: " + playerOid + ", con=" + con + " login failed disconect player");
                           }

                           con.setAssociation((Object)null);
                           if (this.perceptionFilter.removeTarget(playerOid)) {
                              FilterUpdate filterUpdate = new FilterUpdate(1);
                              filterUpdate.removeFieldValue(1, playerOid);
                              Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
                              this.responderFilter.removeTarget(playerOid);
                              this.responderFilter2.removeTarget(playerOid);
                              Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
                              Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
                           }

                           this.playerManager.removeStaticPerception(player, playerOid);
                           this.playerManager.removePlayer(playerOid);
                           Prometheus.registry().counter("rdp_connection_closed", new String[]{"reason", "bad_login"}).increment();
                           con.close();
                        } else {
                           this.proxyLoginCallback.postSpawn(player, con);
                           this.playerManager.loginComplete(player, this.eventQQ);
                           SubjectMessage loginSpawned = new SubjectMessage(MSG_TYPE_LOGIN_SPAWNED);
                           loginSpawned.setSubject(playerOid);
                           Engine.getAgent().sendBroadcast(loginSpawned);
                           this.processPlayerIgnoreList(player);
                           OID accountID = (OID)EnginePlugin.getObjectProperty(playerOid, WorldManagerClient.NAMESPACE, "accountId");
                           this.clientConnections.put(accountID, con);
                           if (player.getStatus() == 3) {
                              atavism.server.plugins.ProxyPlugin.ConnectionResetMessage message = new atavism.server.plugins.ProxyPlugin.ConnectionResetMessage(this, con, player);
                              message.setEnqueueTime();
                              this.messageQQ.insert(player, message);
                           }
                        }

                        Prometheus.registry().counter("player_login_result", new String[]{"status", loginOK ? "ok" : "failed"}).increment();
                        if (Log.loggingDebug) {
                           log.debug("processLogin: loginOK?:" + loginOK + " || player=" + player);
                           log.debug("processLogin: loginOK:" + loginOK + " end");
                        }

                        return loginOK;
                     }
                  }
               }
            }
         }
      }
   }

   protected boolean loadPlayerObject(Player player) {
      if (Log.loggingDebug) {
         log.debug("loadPlayerObject player " + player);
      }

      InstanceRestorePoint restorePoint = null;
      LinkedList restoreStack = null;
      boolean first = true;
      OID playerOid = player.getOid();
      List<Namespace> namespaces = new ArrayList();
      OID oidResult = ObjectManagerClient.loadSubObject(playerOid, namespaces);
      if (Log.loggingDebug) {
         log.debug("loadPlayerObject player " + player + " oidResult=" + oidResult);
      }

      if (oidResult == null) {
         return false;
      } else {
         Point location = new Point();
         OID instanceOid = Engine.getDatabase().getLocation(playerOid, WorldManagerClient.NAMESPACE, location);
         if (Log.loggingDebug) {
            log.debug("loadPlayerObject instanceOid " + instanceOid + " instanceEntryAllowed:" + this.instanceEntryAllowed(playerOid, instanceOid, location));
         }

         if (Log.loggingDebug) {
            log.debug("loadPlayerObject: trying to load player into instance: " + instanceOid);
         }

         int guildID = this.aDB.GetGuildId(playerOid);
         if (Log.loggingDebug) {
            log.debug("loadPlayerObject: load player guildID: " + guildID);
         }

         while(true) {
            try {
               OID result = null;
               if (this.instanceEntryAllowed(playerOid, instanceOid, location)) {
                  InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145);
                  if (Log.loggingDebug) {
                     log.debug("loadPlayerObject InstanceInfo " + instanceInfo + " plyOid=" + instanceInfo.playerOid + " tempId" + instanceInfo.templateID + " groupId" + instanceInfo.groupOid + " guildId" + instanceInfo.guildId + " start do ");
                  }

                  if (instanceInfo.oid != null && (instanceInfo.populationLimit < 1 || instanceInfo.playerPopulation < instanceInfo.populationLimit)) {
                     result = ObjectManagerClient.loadObject(playerOid);
                     if (Log.loggingDebug) {
                        Log.debug("loadPlayerObject: loading player into instance: " + instanceInfo.oid + " of ID: " + instanceInfo.templateID);
                     }
                  }
               }

               if (restoreStack != null && !restorePoint.getFallbackFlag()) {
                  EnginePlugin.setObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack", restoreStack);
               }

               if (result == null) {
                  if (first) {
                     Integer instanceID = (Integer)EnginePlugin.getObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "currentInstanceName");
                     if (Log.loggingDebug) {
                        log.debug("Failed initial load, retrying with current instanceID=" + instanceID);
                     }

                     if (Log.loggingDebug) {
                        log.debug(" loadPlayerObject instanceID=" + instanceID + "  playerOid=" + playerOid + " guildID=" + guildID);
                     }

                     if (instanceID > 0) {
                        instanceOid = this.instanceEntryCallback.selectInstance(player, instanceID, playerOid, guildID);
                        if (Log.loggingDebug) {
                           log.debug("loadPlayerObject instanceOid:" + instanceOid);
                        }

                        if (instanceOid != null) {
                           InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145, false);
                           if (Log.loggingDebug) {
                              log.debug(" loadPlayerObject InstanceInfo " + instanceInfo + " plyOid=" + instanceInfo.playerOid + " tempId=" + instanceInfo.templateID + " groupId=" + instanceInfo.groupOid + " guildId=" + instanceInfo.guildId);
                           }

                           if (instanceInfo.oid != null) {
                              if (instanceInfo.populationLimit > 0 && instanceInfo.playerPopulation >= instanceInfo.populationLimit) {
                                 if (Log.loggingDebug) {
                                    Log.debug("POP: got population: " + instanceInfo.playerPopulation + " and limit: " + instanceInfo.populationLimit);
                                 }

                                 instanceOid = handleFullInstance(instanceInfo.templateID, instanceInfo);
                                 instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145);
                                 log.debug(" loadPlayerObject 2 InstanceInfo " + instanceInfo + " plyOid" + instanceInfo.playerOid + " tempId=" + instanceInfo.templateID + " groupId=" + instanceInfo.groupOid + " guildId=" + instanceInfo.guildId);
                              }

                              if (Log.loggingDebug) {
                                 log.debug("Failed initial load, retrying with instanceOid=" + instanceOid + " and instanceName: " + instanceInfo.name);
                              }

                              BasicWorldNode wnode = new BasicWorldNode();
                              wnode.setInstanceOid(instanceOid);
                              ObjectManagerClient.fixWorldNode(playerOid, wnode);
                              first = false;
                              continue;
                           }
                        }
                     }
                  }

                  if (restorePoint != null && restorePoint.getFallbackFlag()) {
                     if (Log.loggingDebug) {
                        log.debug("loadPlayerObject instanceOid " + instanceOid + " restorePoint:" + restorePoint + " restorePoint.getFallbackFlag():" + restorePoint.getFallbackFlag() + " return false");
                     }

                     return false;
                  }

                  restoreStack = (LinkedList)EnginePlugin.getObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack");
                  if (restoreStack != null && restoreStack.size() != 0) {
                     int size = restoreStack.size();
                     restorePoint = (InstanceRestorePoint)restoreStack.get(size - 1);
                     instanceOid = restorePoint.getInstanceOid();
                     if (restorePoint.getInstanceID() > 0) {
                        instanceOid = this.instanceEntryCallback.selectInstance(player, restorePoint.getInstanceID());
                        if (Log.loggingDebug) {
                           Log.debug("Failed finding matching instance, retrying with restore point instanceID=" + restorePoint.getInstanceID() + " result: " + instanceOid);
                        }
                     }

                     if (instanceOid != null) {
                        BasicWorldNode wnode = new BasicWorldNode();
                        wnode.setInstanceOid(instanceOid);
                        wnode.setLoc(restorePoint.getLoc());
                        wnode.setOrientation(restorePoint.getOrientation());
                        wnode.setDir(new AOVector(0.0F, 0.0F, 0.0F));
                        boolean rc = ObjectManagerClient.fixWorldNode(playerOid, wnode);
                        if (!rc) {
                           if (Log.loggingDebug) {
                              log.debug("loadPlayerObject instanceOid " + instanceOid + " rc:" + rc + " return false");
                           }

                           return false;
                        }

                        location = restorePoint.getLoc();
                     }

                     first = false;
                     if (!restorePoint.getFallbackFlag()) {
                        restoreStack.remove(size - 1);
                     }
                     continue;
                  }

                  Log.error("Failed finding matching instance, and restore stack is null or empty?" + restoreStack + " return false");
                  return false;
               }

               if (restorePoint != null) {
                  EnginePlugin.setObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "currentInstanceName", restorePoint.getInstanceID());
                  if (Log.loggingDebug) {
                     log.debug("INSTANCE: setting current instance prop: " + restorePoint.getInstanceID());
                  }
               }
            } catch (Exception var15) {
               log.error("loadPlayerObject instanceOid " + instanceOid + " Exception: " + var15.getMessage() + " " + var15.getLocalizedMessage());
            }

            if (Log.loggingDebug) {
               log.debug("loadPlayerObject instanceOid " + instanceOid + " END return true");
            }

            return true;
         }
      }
   }

   protected boolean processLoginHelper(ClientConnection con, Player player) {
      OID playerOid = player.getOid();
      ObjectInfo objInfo = WorldManagerClient.getObjectInfo(playerOid);
      if (objInfo == null) {
         Log.error("processLogin: Could not get player ObjectInfo oid=" + playerOid);
         return false;
      } else {
         if (Log.loggingDebug) {
            log.debug("processLoginHelper objInfo " + objInfo.instanceOid);
         }

         if (World.FollowsTerrainOverride != null) {
            Log.debug("using follows terrain override");
            objInfo.followsTerrain = World.FollowsTerrainOverride;
         }

         if (Log.loggingDebug) {
            Log.debug("processLogin: got object info: " + objInfo);
         }

         player.setName(objInfo.name);
         InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(objInfo.instanceOid, -262145);
         if (Log.loggingDebug) {
            log.debug("InstanceInfo " + instanceInfo + " " + instanceInfo.playerOid + " " + instanceInfo.templateID + " " + instanceInfo.groupOid + " " + instanceInfo.guildId);
         }

         if (instanceInfo == null) {
            Log.error("processLogin: unknown instanceOid=" + objInfo.instanceOid);
            return false;
         } else {
            if (Log.loggingDebug) {
               Log.debug("processLogin: sending template (scene) name: " + instanceInfo.templateName);
            }

            Event worldFileEvent = new WorldFileEvent(instanceInfo.templateName);
            con.send(worldFileEvent.toBytes());
            player.sceneLoading(true);
            Log.debug("INFO: process login helper");
            con.send(objInfo.toBuffer(playerOid));
            DisplayContext dc = WorldManagerClient.getDisplayContext(playerOid);
            ModelInfoEvent modelInfoEvent = new ModelInfoEvent(playerOid);
            modelInfoEvent.setDisplayContext(dc);
            if (Log.loggingDebug) {
               Log.debug("processLogin: got dc: " + dc);
            }

            con.send(modelInfoEvent.toBytes());
            Map<String, DisplayContext> childMap = dc.getChildDCMap();
            if (childMap != null && !childMap.isEmpty()) {
               Iterator var10 = childMap.keySet().iterator();

               while(var10.hasNext()) {
                  String slot = (String)var10.next();
                  DisplayContext attachDC = (DisplayContext)childMap.get(slot);
                  if (attachDC == null) {
                     throw new AORuntimeException("attach DC is null for obj: " + playerOid);
                  }

                  OID attacheeOID = attachDC.getObjRef();
                  if (attacheeOID == null) {
                     throw new AORuntimeException("attachee oid is null for obj: " + playerOid);
                  }

                  if (Log.loggingDebug) {
                     Log.debug("processLogin: sending attach message to " + playerOid + " attaching to obj " + playerOid + ", object being attached=" + attacheeOID + " to slot " + slot + ", attachmentDC=" + attachDC);
                  }

                  AttachEvent event = new AttachEvent(playerOid, attacheeOID, slot, attachDC);
                  con.send(event.toBytes());
               }

               Log.debug("processLogin: done with processing attachments");
            }

            if (this.perceptionFilter.addTarget(playerOid)) {
               FilterUpdate filterUpdate = new FilterUpdate(1);
               filterUpdate.addFieldValue(1, playerOid);
               Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
               this.responderFilter.addTarget(playerOid);
               this.responderFilter2.addTarget(playerOid);
               Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
               Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
            }

            LoginMessage loginMessage = new LoginMessage(playerOid, objInfo.name);
            loginMessage.setInstanceOid(objInfo.instanceOid);
            loginMessage.setProxy(this.getName());
            atavism.server.plugins.ProxyPlugin.AsyncRPCCallback asyncRPCCallback = new atavism.server.plugins.ProxyPlugin.AsyncRPCCallback(player, "processLogin: got LoginMessage response");
            int expectedResponses = Engine.getAgent().sendBroadcastRPC(loginMessage, asyncRPCCallback);
            asyncRPCCallback.waitForResponses(expectedResponses);
            WorldManagerClient.updateObject(playerOid, playerOid);
            TargetedExtensionMessage spawnBegin = new TargetedExtensionMessage(playerOid, playerOid);
            spawnBegin.setExtensionType("ao.SCENE_BEGIN");
            spawnBegin.setProperty("action", "login");
            spawnBegin.setProperty("name", instanceInfo.name);
            spawnBegin.setProperty("templateName", instanceInfo.templateName);
            TargetedExtensionMessage spawnEnd = new TargetedExtensionMessage(playerOid, playerOid);
            spawnEnd.setExtensionType("ao.SCENE_END");
            spawnEnd.setProperty("action", "login");
            spawnEnd.setProperty("name", instanceInfo.name);
            spawnEnd.setProperty("templateName", instanceInfo.templateName);
            Integer perceptionCount = WorldManagerClient.spawn(playerOid, spawnBegin, spawnEnd);
            if (perceptionCount < 0) {
               Log.error("processLogin: spawn failed error=" + perceptionCount + " playerOid=" + playerOid);
               return perceptionCount == -2 ? false : false;
            } else {
               if (perceptionCount == 0 && player.supportsLoadingState()) {
                  player.setLoadingState(1);
                  con.send((new LoadingStateEvent(false)).toBytes());
               }

               if (Log.loggingDebug) {
                  Log.debug("processLogin: During login, perceptionCount is " + perceptionCount);
                  Log.debug("processLogin: spawned player, master playerOid=" + playerOid);
               }

               if (Log.loggingDebug) {
                  Log.debug("processLogin: sending over instance information for player " + playerOid + ", instance=" + instanceInfo.name + ", instanceOid=" + instanceInfo.oid);
               }

               this.updateInstancePerception(player.getOid(), (OID)null, instanceInfo.oid, instanceInfo.name);
               return true;
            }
         }
      }
   }

   public ProxyLoginCallback getProxyLoginCallback() {
      return this.proxyLoginCallback;
   }

   public void setProxyLoginCallback(ProxyLoginCallback callback) {
      this.proxyLoginCallback = callback;
   }

   private boolean instanceEntryAllowed(OID playerOid, OID instanceOid, Point location) {
      return instanceOid == null ? false : this.instanceEntryCallback.instanceEntryAllowed(playerOid, instanceOid, location);
   }

   public InstanceEntryCallback getInstanceEntryCallback() {
      return this.instanceEntryCallback;
   }

   public void setInstanceEntryCallback(InstanceEntryCallback callback) {
      this.instanceEntryCallback = callback;
   }

   public void processRequestQuestInfo(ClientConnection con, RequestQuestInfo event) {
      OID npcOid = event.getQuestNpcOid();
      Player player = this.verifyPlayer("processRequestQuestInfo", event, con);
      if (Log.loggingDebug) {
         Log.debug("processRequestQuestInfo: player=" + player + ", npc=" + npcOid);
      }

      QuestClient.requestQuestInfo(npcOid, player.getOid());
   }

   public void processQuestResponse(ClientConnection con, QuestResponse event) {
      Player player = this.verifyPlayer("processQuestResponse", event, con);
      boolean acceptStatus = event.getResponse();
      OID npcOid = event.getQuestNpcOid();
      OID questOid = event.getQuestId();
      if (Log.loggingDebug) {
         Log.debug("processQuestResponse: player=" + player + ", npcOid=" + npcOid + ", acceptStatus=" + acceptStatus);
      }

      QuestResponseMessage msg = new QuestResponseMessage(npcOid, player.getOid(), questOid, acceptStatus);
      Engine.getAgent().sendBroadcast(msg);
   }

   public void processReqConcludeQuest(ClientConnection con, ConcludeQuest event) {
      Player player = this.verifyPlayer("processReqConcludeQuest", event, con);
      OID mobOid = event.getQuestNpcOid();
      if (Log.loggingDebug) {
         Log.debug("processReqConclude: player=" + player + ", mobOid=" + mobOid);
      }

      QuestClient.requestConclude(mobOid, player.getOid());
   }

   public void connectionReset(ClientConnection con) {
      Player player = (Player)con.getAssociation();
      if (player == null) {
         Log.info("ProxyPlugin: DISCONNECT remote=" + con);
      } else {
         if (Log.loggingInfo) {
            Log.info("ProxyPlugin: DISCONNECT remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName() + " player=" + player);
            Log.info("ProxyPlugin: DISCONNECT remote=" + con + " player=" + player);
         }

         this.playerManager.logout(player);
         atavism.server.plugins.ProxyPlugin.ConnectionResetMessage message = new atavism.server.plugins.ProxyPlugin.ConnectionResetMessage(this, con, player);
         message.setEnqueueTime();
         this.messageQQ.insert(player, message);
      }
   }

   protected void processConnectionResetInternal(atavism.server.plugins.ProxyPlugin.ConnectionResetMessage message) {
      long startTime = System.currentTimeMillis();
      ClientConnection con = message.getConnection();
      Player player = message.getPlayer();
      OID playerOid = player.getOid();
      if (Log.loggingInfo) {
         Log.info("ProxyPlugin: LOGOUT_BEGIN remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName());
      }

      if (player.getStatus() != 3) {
         log.error("processConnectionReset: player status is " + Player.statusToString(player.getStatus()) + " should be " + Player.statusToString(3));
         player.setStatus(3);
      }

      try {
         try {
            if (!WorldManagerClient.despawn(playerOid)) {
               log.warn("processConnectionReset: despawn player failed for " + playerOid);
            }
         } catch (Exception var13) {
            log.warn("processConnectionReset: despawn player failed for " + playerOid + " " + var13);
         }

         if (Log.loggingDebug) {
            Log.debug("processConnectionResetInternal Removing perceptionFilter for palyer: " + playerOid);
         }

         if (this.perceptionFilter.removeTarget(playerOid)) {
            FilterUpdate filterUpdate = new FilterUpdate(1);
            filterUpdate.removeFieldValue(1, playerOid);
            if (Log.loggingDebug) {
               Log.debug("processConnectionResetInternal Removing perceptionFilter applyFilterUpdate for palyer: " + playerOid);
            }

            Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
            if (Log.loggingDebug) {
               Log.debug("processConnectionResetInternal Removing responderFilter for palyer: " + playerOid);
            }

            this.responderFilter.removeTarget(playerOid);
            this.responderFilter2.removeTarget(playerOid);
            if (Log.loggingDebug) {
               Log.debug("processConnectionResetInternal Removing perceptionFilter applyFilterUpdate for palyer: " + playerOid);
            }

            Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
            Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
         }

         LogoutMessage logoutMessage = new LogoutMessage(playerOid, player.getName());
         if (Log.loggingDebug) {
            Log.debug("processConnectionResetInternal: Send LogoutMessage for player: " + playerOid + "  and wait for response");
         }

         atavism.server.plugins.ProxyPlugin.AsyncRPCCallback asyncRPCCallback = new atavism.server.plugins.ProxyPlugin.AsyncRPCCallback(player, "processLogout: got LogoutMessage response");
         int expectedResponses = Engine.getAgent().sendBroadcastRPC(logoutMessage, asyncRPCCallback);
         if (Log.loggingDebug) {
            Log.debug("processConnectionResetInternal: Send LogoutMessage for player: " + playerOid + "  and wait for response expectedResponses=" + expectedResponses);
         }

         asyncRPCCallback.waitForResponses(expectedResponses);
         OID accountID = this.aDB.getAccountForCharacter(playerOid);
         if (Log.loggingDebug) {
            Log.debug("Removing connection from client connection map for account: " + accountID);
         }

         if (this.clientConnections.containsKey(accountID) && ((ClientConnection)this.clientConnections.get(accountID)).isOpen()) {
            Prometheus.registry().counter("rdp_connection_closed", new String[]{"reason", "internal_reset"}).increment();
            ((ClientConnection)this.clientConnections.get(accountID)).close();
         }

         this.clientConnections.remove(accountID);
         if (!ObjectManagerClient.unloadObject(playerOid)) {
            log.warn("processConnectionReset: unloadObject failed oid=" + playerOid);
         }
      } catch (NoRecipientsException var14) {
         log.exception("ProxyPlugin.processConnectionResetInternal(): NoRecipientsException ", var14);
      } catch (RPCTimeoutException var15) {
         log.exception("ProxyPlugin.processConnectionResetInternal(): RPCTimeoutException ", var15);
      } catch (Exception var16) {
         log.exception("ProxyPlugin.processConnectionResetInternal(): Exception ", var16);
      }

      this.messageQQ.removeKey(player);
      this.eventQQ.removeKey(player);
      con.closeAggregator();
      this.playerManager.removeStaticPerception(player, playerOid);
      this.playerManager.removePlayer(playerOid);
      if (Log.loggingInfo) {
         Log.info("ProxyPlugin: LOGOUT_END remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName() + " in-queue=" + (startTime - message.getEnqueueTime()) + " processing=" + (System.currentTimeMillis() - startTime) + " nPlayers=" + this.playerManager.getPlayerCount());
      }

      synchronized(player) {
         player.clearConnection();
         player.notifyAll();
      }
   }

   protected void processPlayerHa(ClientConnection con, PlayerHaEvent event) {
      if (Log.loggingDebug) {
         Log.debug("processPlayerHa: got dir loc orient event: " + event);
      }

      Player player = this.verifyPlayer("processPlayerHa", event, con);
      long stime = System.currentTimeMillis();
      long ctime = event.getTime();
      long lctime = 0L;
      long lstime = 0L;

      try {
         lctime = (Long)this.playerLastClientTime.get(player.getOid());
      } catch (Exception var20) {
      }

      try {
         lstime = (Long)this.playerLastServerTime.get(player.getOid());
      } catch (Exception var19) {
      }

      this.playerLastClientTime.put(player.getOid(), event.getTime());
      this.playerLastServerTime.put(player.getOid(), stime);
      if (lctime > 0L && lstime > 0L && stime - lstime < (long)SpeedhackMinDiff) {
         log.error("SPEEDHACK detected plyOid=" + player.getOid() + " Ct=" + ctime + " LCT=" + lctime + " ST=" + stime + " LST=" + lstime + " dst=" + (stime - lstime) + " dct=" + (ctime - lctime));
         long count = 0L;

         try {
            count = (Long)this.playerSpeedHackCount.get(player.getOid());
         } catch (Exception var18) {
         }

         ++count;
         this.playerSpeedHackCount.put(player.getOid(), count);
         long fdtime = 0L;

         try {
            fdtime = (Long)this.playerFirstSpeedHackTime.get(player.getOid());
         } catch (Exception var17) {
         }

         if (fdtime == 0L) {
            fdtime = stime;
            this.playerFirstSpeedHackTime.put(player.getOid(), stime);
         }

         if (SpeedhackChatMsg.length() > 1) {
            TargetedComMessage comMsg = new TargetedComMessage();
            comMsg.setString(SpeedhackChatMsg);
            comMsg.setChannel(0);
            comMsg.setChatterName("Admin");
            comMsg.setTarget(player.getOid());
            Engine.getAgent().sendBroadcast(comMsg);
         }

         HashMap<String, Serializable> logData = new HashMap();
         logData.put("serverDeltaTime", stime - lstime);
         logData.put("clientDeltaTime", ctime - lctime);
         logData.put("firstDetection", fdtime);
         logData.put("count", count);
         DataLoggerClient.logData("SPEEDHACK", player.getOid(), (OID)null, (OID)null, logData);
         if (count > (long)SpeedhackCountToDisconect) {
            Prometheus.registry().counter("rdp_connection_closed", new String[]{"reason", "speed_hack"}).increment();
            con.close();
            this.playerLastClientTime.remove(player.getOid());
            this.playerLastServerTime.remove(player.getOid());
            this.playerFirstSpeedHackTime.remove(player.getOid());
            this.playerSpeedHackCount.remove(player.getOid());
         }
      }

   }

   protected void processDirLocOrient(ClientConnection con, DirLocOrientEvent event) {
      if (Log.loggingDebug) {
         Log.debug("processDirLocOrient: got dir loc orient event: " + event);
      }

      Player player = this.verifyPlayer("processDirLoc", event, con);
      BasicWorldNode wnode = new BasicWorldNode();
      wnode.setDir(event.getDir());
      wnode.setLoc(event.getLoc());
      wnode.setOrientation(event.getQuaternion());
      wnode.time = event.getTime();
      wnode.mid = event.getId();
      wnode.cid = event.getUId();
      WorldManagerClient.updateWorldNode(player.getOid(), wnode);
   }

   protected void processCom(ClientConnection con, ComEvent event) {
      Player player = this.verifyPlayer("processCom", event, con);
      if (Log.loggingInfo) {
         Log.info("ProxyPlugin: CHAT_SENT player=" + player + " channel=" + event.getChannelId() + " msg=[" + event.getMessage() + "]");
      }

      log.debug("processCom: CHAT_SENT");
      if (!this.aDB.isOnBlackList(player.getOid(), event.getObjectOid())) {
         this.incrementChatCount();
         ChatClient.sendChatMsg(player.getOid(), player.getName(), event.getChannelId(), event.getMessage());
      }
   }

   protected void processCommand(ClientConnection con, CommandEvent event) {
      Player player = this.verifyPlayer("processCommand", event, con);
      String cmd = event.getCommand().split(" ")[0];
      if (Log.loggingDebug) {
         log.debug("processCommand: cmd=" + cmd + ", fullCmd=" + event.getCommand());
      }

      this.commandMapLock.lock();

      atavism.server.plugins.ProxyPlugin.RegisteredCommand command;
      try {
         command = (atavism.server.plugins.ProxyPlugin.RegisteredCommand)this.commandMap.get(cmd);
      } finally {
         this.commandMapLock.unlock();
      }

      if (command == null) {
         Log.warn("processCommand: no parser for command: " + event.getCommand());
         command = (atavism.server.plugins.ProxyPlugin.RegisteredCommand)this.commandMap.get("/unknowncmd");
         if (command != null) {
            Engine.setCurrentPlugin(this);
            command.parser.parse(event);
            Engine.setCurrentPlugin((EnginePlugin)null);
         }

      } else {
         Engine.setCurrentPlugin(this);
         if (command.access.allowed(event, this)) {
            command.parser.parse(event);
         } else {
            Log.warn("Player " + player + " not allowed to run command '" + event.getCommand() + "'");
         }

         Engine.setCurrentPlugin((EnginePlugin)null);
      }
   }

   protected void processAutoAttack(ClientConnection con, AutoAttackEvent event) {
      CombatClient.autoAttack(event.getAttackerOid(), event.getTargetOid(), event.getAttackStatus());
   }

   protected void processActivateItem(ClientConnection con, ActivateItemEvent event) {
      InventoryClient.activateObject(event.getItemOid(), event.getObjectOid(), event.getTargetOid());
   }

   protected void processAbilityStatusEvent(ClientConnection con, AbilityStatusEvent event) {
      Player player = (Player)con.getAssociation();
      AbilityStatusMessage msg = new AbilityStatusMessage(CombatClient.MSG_TYPE_ABILITY_STATUS, player.getOid(), event.getPropertyMap());
      Engine.getAgent().sendBroadcast(msg);
   }

   protected void processLogout(ClientConnection con, LogoutEvent event) {
   }

   protected void processSceneLoaded(ClientConnection con, SceneLoadedEvent event) {
      Player player = (Player)con.getAssociation();
      player.sceneLoading(false);
      if (Log.loggingDebug) {
         Log.debug("SCENE: sceneLoading set to false for player: " + player.getOid());
      }

   }

   protected void processExtensionMessageEvent(ClientConnection con, ExtensionMessageEvent event) {
      String key = (String)event.getPropertyMap().get("ext_msg_subtype");
      OID target = event.getTargetOid();
      Player player = (Player)con.getAssociation();
      if (Log.loggingDebug) {
         Log.debug("processExtensionMessageEvent: " + player + " subType=" + key + " target=" + target);
      }

      List<ProxyExtensionHook> proxyHookList = (List)this.extensionHooks.get(key);
      if (proxyHookList == null) {
         if (target != null) {
            TargetedExtensionMessage msg = new TargetedExtensionMessage(WorldManagerClient.MSG_TYPE_EXTENSION, target, player.getOid(), event.getClientTargeted(), event.getPropertyMap());
            if (event.getClientTargeted()) {
               msg.setMsgType(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
               if (this.allowClientToClientMessage(player, target, msg)) {
                  Engine.getAgent().sendBroadcast(msg);
               }
            } else {
               MessageType msgType = this.getExtensionMessageType(key);
               if (msgType == null) {
                  Log.error("processExtensionMessageEvent: key '" + key + "' has no corresponding MessageType");
                  return;
               }

               msg.setMsgType(msgType);
               Engine.getAgent().sendBroadcast(msg);
            }
         } else {
            MessageType msgType = this.getExtensionMessageType(key);
            if (msgType == null) {
               Log.error("processExtensionMessageEvent: key '" + key + "' has no corresponding MessageType");
               return;
            }

            ExtensionMessage msg = new ExtensionMessage(msgType, player.getOid(), event.getPropertyMap());
            Engine.getAgent().sendBroadcast(msg);
         }

      } else {
         Iterator var7 = proxyHookList.iterator();

         while(var7.hasNext()) {
            ProxyExtensionHook hook = (ProxyExtensionHook)var7.next();
            hook.processExtensionEvent(event, player, this);
         }

      }
   }

   public void registerExtensionSubtype(String subtype, MessageType type) {
      this.extensionMessageRegistry.put(subtype, type);
   }

   public MessageType unregisterExtensionSubtype(String subtype) {
      return (MessageType)this.extensionMessageRegistry.remove(subtype);
   }

   public MessageType getExtensionMessageType(String subtype) {
      return (MessageType)this.extensionMessageRegistry.get(subtype);
   }

   public boolean allowClientToClientMessage(Player sender, OID targetOid, TargetedExtensionMessage message) {
      return this.defaultAllowClientToClientMessage;
   }

   protected boolean specialCaseNewProcessing(ObjectNote objectNote, Player player) {
      long start = System.currentTimeMillis();
      ClientConnection con = player.getConnection();
      OID objOid = objectNote.getSubject();
      ObjectType objType = objectNote.getObjectType();
      if (objType == ObjectTypes.light) {
         Log.debug("specialCaseNewProcessing: got a light object");
         LightData lightData = (LightData)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, Light.LightDataPropertyKey);
         if (Log.loggingDebug) {
            Log.debug("specialCaseNewProcessing: light data=" + lightData);
         }

         NewLightEvent lightEvent = new NewLightEvent(player.getOid(), objOid, lightData);
         con.send(lightEvent.toBytes());
         return true;
      } else if (objType.equals(WorldManagerClient.TEMPL_OBJECT_TYPE_TERRAIN_DECAL)) {
         Log.debug("specialCaseNewProcessing: got a terrain decal object");
         TerrainDecalData decalData = (TerrainDecalData)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
         if (Log.loggingDebug) {
            Log.debug("specialCaseNewProcessing: terrain decal data=" + decalData);
         }

         NewTerrainDecalEvent decalEvent = new NewTerrainDecalEvent(objOid, decalData);
         con.send(decalEvent.toBytes());
         return true;
      } else if (objType.equals(WorldManagerClient.TEMPL_OBJECT_TYPE_POINT_SOUND)) {
         Log.debug("specialCaseNewProcessing: got a point sound object");
         List<SoundData> soundData = (List)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, WorldManagerClient.TEMPL_SOUND_DATA_LIST);
         if (Log.loggingDebug) {
            Log.debug("specialCaseNewProcessing: sound data=" + soundData);
         }

         SoundMessage soundMsg = new SoundMessage(objOid);
         soundMsg.setSoundData(soundData);
         con.send(soundMsg.toBuffer());
         return true;
      } else {
         PerceptionInfo perceptionInfo = (PerceptionInfo)objectNote.getObjectInfo();
         if (perceptionInfo.objectInfo == null) {
            return true;
         } else {
            MobPathMessage pathMsg = (MobPathMessage)perceptionInfo.objectInfo.getProperty(WorldManagerClient.MOB_PATH_PROPERTY);
            if (Log.loggingDebug) {
               Log.debug("INFO: MobPathMessage special case with player/npc: " + perceptionInfo.objectInfo.name);
            }

            con.send(perceptionInfo.objectInfo.toBuffer(player.getOid()));
            if (Log.loggingDebug) {
               Log.debug("INFO: specialCaseNewProcessing " + perceptionInfo.displayContext);
            }

            if (perceptionInfo.displayContext != null) {
               ModelInfoEvent modelInfoEvent = new ModelInfoEvent(objOid);
               modelInfoEvent.setDisplayContext(perceptionInfo.displayContext);
               con.send(modelInfoEvent.toBytes());
            } else if (Log.loggingDebug) {
               Log.debug("No display context for " + objOid + " " + perceptionInfo.objectInfo);
            }

            if (pathMsg != null) {
               if (pathMsg.pathExpired()) {
                  if (Log.loggingDebug) {
                     Log.debug("specialCaseNewProcessing: for mob " + objOid + ", last mob path expired " + pathMsg.toString());
                  }
               } else {
                  if (Log.loggingDebug) {
                     Log.debug("specialCaseNewProcessing: for mob " + objOid + ", sending last mob path " + pathMsg.toString());
                  }

                  AOByteBuffer pathBuf = pathMsg.toBuffer();
                  con.send(pathBuf);
               }
            }

            Map<String, DisplayContext> childMap = null;
            if (perceptionInfo.displayContext != null) {
               childMap = perceptionInfo.displayContext.getChildDCMap();
            }

            if (childMap != null && !childMap.isEmpty()) {
               Iterator var11 = childMap.keySet().iterator();

               while(var11.hasNext()) {
                  String slot = (String)var11.next();
                  DisplayContext attachDC = (DisplayContext)childMap.get(slot);
                  if (attachDC == null) {
                     throw new AORuntimeException("attach DC is null for obj: " + objOid);
                  }

                  OID attacheeOID = attachDC.getObjRef();
                  if (attacheeOID == null) {
                     throw new AORuntimeException("attachee oid is null for obj: " + objOid);
                  }

                  if (Log.loggingDebug) {
                     Log.debug("specialCaseNewProcessing: sending attach message to " + player.getOid() + " attaching to obj " + objOid + ", object being attached=" + attacheeOID + " to slot " + slot + ", attachmentDC=" + attachDC);
                  }

                  AttachEvent event = new AttachEvent(objOid, attacheeOID, slot, attachDC);
                  con.send(event.toBytes());
               }

               if (Log.loggingDebug) {
                  Log.debug("specialCaseNewProcessing: done with processing attachments");
               }
            }

            long finish = System.currentTimeMillis();
            if (Log.loggingDebug) {
               Log.debug("specialCaseNewProcessing: finished.\tplayerOid=" + player.getOid() + ", oid=" + objOid + " in " + (finish - start) + " ms");
            }

            return false;
         }
      }
   }

   protected boolean specialCaseFreeProcessing(ObjectNote objectNote, Player player) {
      if (player.getOid().equals(objectNote.getSubject())) {
         Log.debug("ignoring free object message to self");
         return true;
      } else {
         ClientConnection con = player.getConnection();
         if (!con.isOpen()) {
            con = null;
         }

         OID objOid = objectNote.getSubject();
         if (objectNote.getObjectType() == ObjectTypes.road) {
            if (Log.loggingDebug) {
               Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", roadSegmentOid=" + objOid);
            }

            this.handleFreeRoad(con, objOid);
            return true;
         } else if (objectNote.getObjectType().equals(WorldManagerClient.TEMPL_OBJECT_TYPE_TERRAIN_DECAL)) {
            if (Log.loggingDebug) {
               Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", decalOid=" + objOid);
            }

            FreeTerrainDecalEvent decalEvent = new FreeTerrainDecalEvent(objOid);
            if (con != null) {
               con.send(decalEvent.toBytes());
            }

            return true;
         } else {
            if (Log.loggingDebug) {
               Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", objOid=" + objOid);
            }

            NotifyFreeObjectEvent freeEvent = new NotifyFreeObjectEvent(player.getOid(), objOid);
            if (con != null) {
               con.send(freeEvent.toBytes());
            }

            return false;
         }
      }
   }

   protected void handleFreeRoad(ClientConnection con, OID objOid) {
      FreeRoadMessage freeRoadMsg = new FreeRoadMessage(objOid);
      AOByteBuffer buf = freeRoadMsg.toBuffer();
      if (con != null) {
         con.send(buf);
      }

   }

   public static void addStaticPerception(OID playerOid, OID oid) {
      addStaticPerception(playerOid, oid, (String)null, (ObjectType)null, false);
   }

   public static void addStaticPerception(OID oid, OID oid2, String name, ObjectType type) {
      addStaticPerception(oid, oid2, name, type, true);
   }

   private static void addStaticPerception(OID playerOid, OID oid, String name, ObjectType type, boolean hasObjectInfo) {
      atavism.server.plugins.ProxyPlugin.AddStaticPerceptionMessage message = new atavism.server.plugins.ProxyPlugin.AddStaticPerceptionMessage(MSG_TYPE_ADD_STATIC_PERCEPTION);
      message.setTarget(playerOid);
      message.setSubject(oid);
      message.setName(name);
      message.setType(type);
      message.setHasObjectInfo(hasObjectInfo);
      Engine.getAgent().sendBroadcast(message);
   }

   public static void removeStaticPerception(OID playerOid, OID oid) {
      TargetMessage message = new TargetMessage(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
      message.setTarget(playerOid);
      message.setSubject(oid);
      Engine.getAgent().sendBroadcast(message);
   }

   protected void processPlayerIgnoreList(Player player) {
      if (player.getStatus() == 3) {
         Log.error("ProxyPlugin.processPlayerIgnoreList: Aborting... player.getStatus() is STATUS_LOGOUT");
      } else {
         this.sendPlayerIgnoreList(player);
      }
   }

   protected void sendPlayerIgnoreList(Player player) {
      String missing = " Missing ";
   }

   public void updateIgnoredOids(Player player, List<OID> nowIgnored, List<OID> noLongerIgnored) {
   }

   public List<Object> matchingPlayers(Player player, String playerName, Boolean exactMatch) {
      boolean match = exactMatch == null ? true : exactMatch;
      List<Object> matchLists = Engine.getDatabase().getOidsAndNamesMatchingName(playerName, match);
      List<OID> oids = (List)matchLists.get(0);
      List<String> names = (List)matchLists.get(1);
      if (Log.loggingDebug) {
         log.debug("ProxyPlugin.matchingPlayers: For player " + player.getOid() + ", found " + (oids == null ? 0 : oids.size()) + " players: " + Database.makeOidCollectionString(oids) + " " + (match ? "exactly matching" : "starting with") + " name '" + playerName + "':" + Database.makeNameCollectionString(names));
      }

      return matchLists;
   }

   public boolean isOnBlockList2(OID playerOid, OID targetOid) {
      if (Log.loggingDebug) {
         log.debug("IsOnBlockList: SocialPlugin  started for: " + playerOid);
      }

      boolean isOnBlockList = this.aDB.isOnBlackList(playerOid, targetOid);
      String targetName;
      if (isOnBlockList) {
         targetName = WorldManagerClient.getObjectInfo(targetOid).name;
         EventMessageHelper.SendErrorEvent(playerOid, "ErrorPlayerOnBlockList", 0, targetName);
      } else {
         isOnBlockList = this.aDB.isOnBlackList(targetOid, playerOid);
         if (isOnBlockList) {
            targetName = WorldManagerClient.getObjectInfo(targetOid).name;
            EventMessageHelper.SendErrorEvent(playerOid, "ErrorPlayerYourOnBlockList", 0, targetName);
         }
      }

      if (Log.loggingDebug) {
         log.debug("IsOnBlockList: SocialPlugin  finished for: " + playerOid);
      }

      return isOnBlockList;
   }

   private boolean isPlayerConnectionValid(Player player) {
      ClientConnection con = player.getConnection();
      return con != null && con.isOpen();
   }

   public static OID handleFullInstance(int instanceTemplateID, InstanceInfo instanceInfo) {
      if (Log.loggingDebug) {
         Log.debug("POP: instance full with template: " + instanceTemplateID);
      }

      int instanceNum = 1;
      String instanceName = "";
      InstanceTemplate island = InstanceClient.getInstanceTemplate(instanceTemplateID);

      OID instanceOid;
      while(true) {
         instanceName = island.getName() + "_" + instanceNum;
         instanceOid = InstanceClient.getInstanceOid(instanceName);
         if (instanceOid != null) {
            instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145);
            if (instanceInfo.populationLimit < 1 || instanceInfo.playerPopulation < instanceInfo.populationLimit) {
               break;
            }
         } else {
            Template overrideTemplate = new Template();
            overrideTemplate.put(Namespace.INSTANCE, "name", instanceName);
            overrideTemplate.setName(instanceName);
            instanceOid = InstanceClient.createInstance(instanceTemplateID, overrideTemplate);
            if (instanceOid != null) {
               break;
            }
         }

         ++instanceNum;
      }

      return instanceOid;
   }

   private void updateInstancePerception(OID playerOid, OID prevInstanceOid, OID destInstanceOid, String destInstanceName) {
      if (prevInstanceOid != null) {
         removeStaticPerception(playerOid, prevInstanceOid);
      }

      addStaticPerception(playerOid, destInstanceOid, destInstanceName, ObjectTypes.instance);
   }

   protected void pushInstanceRestorePoint(Player player, BasicWorldNode loc) {
      OID playerOid = player.getOid();
      if (Log.loggingDebug) {
         log.debug("pushInstanceRestorePoint " + playerOid);
      }

      InstanceRestorePoint restorePoint = new InstanceRestorePoint();
      restorePoint.setInstanceOid(loc.getInstanceOid());
      restorePoint.setLoc(loc.getLoc());
      restorePoint.setOrientation(loc.getOrientation());
      InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(loc.getInstanceOid(), 8);
      restorePoint.setInstanceID(instanceInfo.templateID);
      LinkedList<Object> restoreStack = (LinkedList)EnginePlugin.getObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack");
      if (restoreStack == null) {
         restoreStack = new LinkedList();
      }

      restoreStack.add(restorePoint);
      EnginePlugin.setObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack", restoreStack);
   }

   protected void sendOceanData(OceanData oceanData, Player player) {
      TargetedExtensionMessage oceanMsg = new ClientParameterMessage(player.getOid());
      oceanMsg.setProperty("Ocean.DisplayOcean", oceanData.displayOcean.toString());
      if (oceanData.useParams != null) {
         oceanMsg.setProperty("Ocean.UseParams", oceanData.useParams.toString());
      }

      if (oceanData.waveHeight != null) {
         oceanMsg.setProperty("Ocean.WaveHeight", oceanData.waveHeight.toString());
      }

      if (oceanData.seaLevel != null) {
         oceanMsg.setProperty("Ocean.SeaLevel", oceanData.seaLevel.toString());
      }

      if (oceanData.bumpScale != null) {
         oceanMsg.setProperty("Ocean.BumpScale", oceanData.bumpScale.toString());
      }

      if (oceanData.bumpSpeedX != null) {
         oceanMsg.setProperty("Ocean.BumpSpeedX", oceanData.bumpSpeedX.toString());
      }

      if (oceanData.bumpSpeedZ != null) {
         oceanMsg.setProperty("Ocean.BumpSpeedZ", oceanData.bumpSpeedZ.toString());
      }

      if (oceanData.textureScaleX != null) {
         oceanMsg.setProperty("Ocean.TextureScaleX", oceanData.textureScaleX.toString());
      }

      if (oceanData.textureScaleZ != null) {
         oceanMsg.setProperty("Ocean.TextureScaleZ", oceanData.textureScaleZ.toString());
      }

      if (oceanData.deepColor != null) {
         oceanMsg.setProperty("Ocean.DeepColor", oceanData.deepColor.toString());
      }

      if (oceanData.shallowColor != null) {
         oceanMsg.setProperty("Ocean.ShallowColor", oceanData.shallowColor.toString());
      }

      player.getConnection().send(oceanMsg.toBuffer(player.getVersion()));
   }

   protected Player verifyPlayer(String context, Event event, ClientConnection con) {
      Player player = (Player)con.getAssociation();
      if (!player.getOid().equals(event.getObjectOid())) {
         throw new AORuntimeException(context + ": con doesn't match player " + player + " against eventOid " + event.getObjectOid());
      } else {
         return player;
      }
   }

   public void incrementChatCount() {
      ++this.chatSentCount;
   }

   public void incrementPrivateChatCount() {
      ++this.privateChatSentCount;
   }

   public void addAdmin(OID oid) {
      if (Log.loggingDebug) {
         log.debug("ProxyPlugin.addAdmin: adding oid " + oid);
      }

      this.lock.lock();

      try {
         this.adminSet.add(oid);
      } finally {
         this.lock.unlock();
      }

   }

   public Set<OID> getAdmins() {
      this.lock.lock();

      HashSet var1;
      try {
         var1 = new HashSet(this.adminSet);
      } finally {
         this.lock.unlock();
      }

      return var1;
   }

   public boolean isAdmin(OID playerOid) {
      this.lock.lock();

      boolean var2;
      try {
         if (playerOid != null) {
            AccountDatabase aDB = new AccountDatabase(false);
            int status = aDB.getCharacterAccountStatus(playerOid);
            boolean var4 = status == 5;
            return var4;
         }

         var2 = false;
      } finally {
         this.lock.unlock();
      }

      return var2;
   }

   public int GetConnectionLimit() {
      return this.connectionLimit;
   }

   protected Object createMBeanInstance() {
      return new atavism.server.plugins.ProxyPlugin.ProxyJMX(this);
   }

   private String getTemp() {
      return "47bedc488b0106b2219dd2e2ff5524fd";
   }

   // $FF: synthetic method
   static SquareQueue access$200(ProxyPlugin x0) {
      return x0.eventQQ;
   }

   // $FF: synthetic method
   static String access$300(ProxyPlugin x0) {
      return x0.getTemp();
   }

   // $FF: synthetic method
   static int access$402(ProxyPlugin x0, int x1) {
      return x0.connectionLimit = x1;
   }

   // $FF: synthetic method
   static int access$400(ProxyPlugin x0) {
      return x0.connectionLimit;
   }

   // $FF: synthetic method
   static ObjectLockManager access$1100(ProxyPlugin x0) {
      return x0.getObjectLockManager();
   }

   // $FF: synthetic method
   static int access$1200(ProxyPlugin x0) {
      return x0.instanceEntryCount;
   }

   // $FF: synthetic method
   static int access$1300(ProxyPlugin x0) {
      return x0.chatSentCount;
   }

   // $FF: synthetic method
   static int access$1400(ProxyPlugin x0) {
      return x0.privateChatSentCount;
   }

   // $FF: synthetic method
   static ExecutorService access$1500(ProxyPlugin x0) {
      return x0.logoutExecutor;
   }

   // $FF: synthetic method
   static boolean access$1600(ProxyPlugin x0, Player x1) {
      return x0.isPlayerConnectionValid(x1);
   }

   // $FF: synthetic method
   static InstanceEntryCallback access$1700(ProxyPlugin x0) {
      return x0.instanceEntryCallback;
   }

   // $FF: synthetic method
   static boolean access$1800(ProxyPlugin x0, OID x1, OID x2, Point x3) {
      return x0.instanceEntryAllowed(x1, x2, x3);
   }

   // $FF: synthetic method
   static void access$1900(ProxyPlugin x0, OID x1, OID x2, OID x3, String x4) {
      x0.updateInstancePerception(x1, x2, x3, x4);
   }

   // $FF: synthetic method
   static int access$1208(ProxyPlugin x0) {
      return x0.instanceEntryCount++;
   }
}
 

предполагаю что здесь)
Java:
private void runCheck() {
      String email = Engine.getProperty("atavism.licence.email");
      String licencekey = Engine.getProperty("atavism.licence.key");
      String proxy_id = Engine.getProperty("atavism.proxy.id");
      int num = 0;
      int proxyId = 0;

      try {
         if (proxy_id != null && proxy_id != "") {
            proxyId = Integer.parseInt(proxy_id);
         }
      } catch (NumberFormatException var18) {
      }

      String[] url = new String[]{"https://apanel.atavismonline.com/login/verifyserver.php", "https://licensing2.dragonsan.com:2443/login/verifyserver.php", "https://licensing1.atavismonline.com/login/verifyserver.php", "https://licensing.dragonsan.com/login/verifyserver.php", "https://licensing1.dragonsan.com/login/verifyserver.php", "https://licensing.atavismonline.com/login/verifyserver.php", "https://licensing2.atavismonline.com/login/verifyserver.php"};
      String resSor = this.howla();
      atavism.server.plugins.ProxyPlugin.rck reCheck = new atavism.server.plugins.ProxyPlugin.rck(this, resSor);
      Engine.getExecutor().scheduleAtFixedRate(reCheck, 300L, 300L, TimeUnit.SECONDS);

      while(num < url.length) {
         boolean failed = false;

         try {
            String res = "";
            URL urlObj = new URL(url[num]);
            URLConnection lu = urlObj.openConnection();
            lu.setConnectTimeout(10000);
            String data = "email=" + URLEncoder.encode(email, "UTF-8") + "&licence=" + URLEncoder.encode(licencekey, "UTF-8") + "&ver=" + URLEncoder.encode("10.7.0", "UTF-8") + "&addr=" + URLEncoder.encode(Engine.getProperty("atavism.proxy.bindaddress"), "UTF-8") + "&sor=" + URLEncoder.encode(resSor, "UTF-8") + "&c=" + URLEncoder.encode("0", "UTF-8") + "&cp=" + this.playerManager.getPlayerCount() + " &pi=" + proxyId + "&build=" + URLEncoder.encode(ServerVersion.getBuildDate(), "UTF-8") + "&m=" + MaxConcurrentUsers;
            lu.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(lu.getOutputStream());
            wr.write(data);
            wr.flush();
            BufferedReader rd = new BufferedReader(new InputStreamReader(lu.getInputStream()));

            for(String line = ""; (line = rd.readLine()) != null; res = res + line) {
            }

            wr.flush();
            wr.close();
            if (debugLic) {
               System.out.println("\n" + url[num] + "\n" + res + "\n");
            }

            res = HelperFunctions.readEncodedString(Base64.decode(res));
            String[] output = res.split(":");
            if (debugLic) {
               System.out.println("\nsec: " + resSor + "\n s: " + HelperFunctions.readEncodedString(Base64.decode(output[2])) + "\n");
            }

            if (EncryptionHelper.passwordMD5Check(output[0], this.getTemp()) && resSor.equals(HelperFunctions.readEncodedString(Base64.decode(output[2])))) {
               this.connectionLimit = Integer.parseInt(HelperFunctions.readEncodedString(Base64.decode(output[1])));
            } else {
               System.out.println("\nLicense verification failed");
               Log.error("License verification failed");
            }

            Log.debug("CONNECTOR: connections set to: " + this.connectionLimit);
         } catch (Exception var19) {
            Log.error("CONNECTOR: failed verifying " + var19);
            if (debugLic) {
               System.out.println("\n" + url[num] + "\n" + var19);
            }

            ++num;
            failed = true;
         }

         if (!failed) {
            return;
         }
      }

      System.out.println("\nLicense verification failed");
      Log.error("License verification failed");
      this.connectionLimit = 0;
   }

   public Map<String, String> getStatusMap() {
      Map<String, String> status = new HashMap();
      status.put("players", Integer.toString(this.playerManager.getPlayerCount()));
      return status;
   }

   public void registerCommand(String command, atavism.server.plugins.ProxyPlugin.CommandParser parser) {
      this.commandMapLock.lock();

      try {
         this.commandMap.put(command, new atavism.server.plugins.ProxyPlugin.RegisteredCommand(parser, this.defaultCommandAccess));
      } finally {
         this.commandMapLock.unlock();
      }

   }

   public void registerCommand(String command, atavism.server.plugins.ProxyPlugin.CommandParser parser, atavism.server.plugins.ProxyPlugin.CommandAccessCheck access) {
      this.commandMapLock.lock();

      try {
         this.commandMap.put(command, new atavism.server.plugins.ProxyPlugin.RegisteredCommand(parser, access));
      } finally {
         this.commandMapLock.unlock();
      }

   }
 
предполагаю что здесь)
Java:
private void runCheck() {
      String email = Engine.getProperty("atavism.licence.email");
      String licencekey = Engine.getProperty("atavism.licence.key");
      String proxy_id = Engine.getProperty("atavism.proxy.id");
      int num = 0;
      int proxyId = 0;

      try {
         if (proxy_id != null && proxy_id != "") {
            proxyId = Integer.parseInt(proxy_id);
         }
      } catch (NumberFormatException var18) {
      }

      String[] url = new String[]{"https://apanel.atavismonline.com/login/verifyserver.php", "https://licensing2.dragonsan.com:2443/login/verifyserver.php", "https://licensing1.atavismonline.com/login/verifyserver.php", "https://licensing.dragonsan.com/login/verifyserver.php", "https://licensing1.dragonsan.com/login/verifyserver.php", "https://licensing.atavismonline.com/login/verifyserver.php", "https://licensing2.atavismonline.com/login/verifyserver.php"};
      String resSor = this.howla();
      atavism.server.plugins.ProxyPlugin.rck reCheck = new atavism.server.plugins.ProxyPlugin.rck(this, resSor);
      Engine.getExecutor().scheduleAtFixedRate(reCheck, 300L, 300L, TimeUnit.SECONDS);

      while(num < url.length) {
         boolean failed = false;

         try {
            String res = "";
            URL urlObj = new URL(url[num]);
            URLConnection lu = urlObj.openConnection();
            lu.setConnectTimeout(10000);
            String data = "email=" + URLEncoder.encode(email, "UTF-8") + "&licence=" + URLEncoder.encode(licencekey, "UTF-8") + "&ver=" + URLEncoder.encode("10.7.0", "UTF-8") + "&addr=" + URLEncoder.encode(Engine.getProperty("atavism.proxy.bindaddress"), "UTF-8") + "&sor=" + URLEncoder.encode(resSor, "UTF-8") + "&c=" + URLEncoder.encode("0", "UTF-8") + "&cp=" + this.playerManager.getPlayerCount() + " &pi=" + proxyId + "&build=" + URLEncoder.encode(ServerVersion.getBuildDate(), "UTF-8") + "&m=" + MaxConcurrentUsers;
            lu.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(lu.getOutputStream());
            wr.write(data);
            wr.flush();
            BufferedReader rd = new BufferedReader(new InputStreamReader(lu.getInputStream()));

            for(String line = ""; (line = rd.readLine()) != null; res = res + line) {
            }

            wr.flush();
            wr.close();
            if (debugLic) {
               System.out.println("\n" + url[num] + "\n" + res + "\n");
            }

            res = HelperFunctions.readEncodedString(Base64.decode(res));
            String[] output = res.split(":");
            if (debugLic) {
               System.out.println("\nsec: " + resSor + "\n s: " + HelperFunctions.readEncodedString(Base64.decode(output[2])) + "\n");
            }

            if (EncryptionHelper.passwordMD5Check(output[0], this.getTemp()) && resSor.equals(HelperFunctions.readEncodedString(Base64.decode(output[2])))) {
               this.connectionLimit = Integer.parseInt(HelperFunctions.readEncodedString(Base64.decode(output[1])));
            } else {
               System.out.println("\nLicense verification failed");
               Log.error("License verification failed");
            }

            Log.debug("CONNECTOR: connections set to: " + this.connectionLimit);
         } catch (Exception var19) {
            Log.error("CONNECTOR: failed verifying " + var19);
            if (debugLic) {
               System.out.println("\n" + url[num] + "\n" + var19);
            }

            ++num;
            failed = true;
         }

         if (!failed) {
            return;
         }
      }

      System.out.println("\nLicense verification failed");
      Log.error("License verification failed");
      this.connectionLimit = 0;
   }

   public Map<String, String> getStatusMap() {
      Map<String, String> status = new HashMap();
      status.put("players", Integer.toString(this.playerManager.getPlayerCount()));
      return status;
   }

   public void registerCommand(String command, atavism.server.plugins.ProxyPlugin.CommandParser parser) {
      this.commandMapLock.lock();

      try {
         this.commandMap.put(command, new atavism.server.plugins.ProxyPlugin.RegisteredCommand(parser, this.defaultCommandAccess));
      } finally {
         this.commandMapLock.unlock();
      }

   }

   public void registerCommand(String command, atavism.server.plugins.ProxyPlugin.CommandParser parser, atavism.server.plugins.ProxyPlugin.CommandAccessCheck access) {
      this.commandMapLock.lock();

      try {
         this.commandMap.put(command, new atavism.server.plugins.ProxyPlugin.RegisteredCommand(parser, access));
      } finally {
         this.commandMapLock.unlock();
      }

   }
Оно то здесь ток , хе как випилиТЬ)
 
Оно то здесь ток , хе как випилиТЬ)
предполагаю что смотреть нужно где идёт вызов функции
вот здесь
Java:
public void onActivate() {
      try {
         PacketAggregator.initializeAggregation(Engine.getProperties());
         String logProxyHistograms = Engine.properties.getProperty("atavism.log_proxy_histograms");
         if (logProxyHistograms != null && logProxyHistograms.equals("true")) {
            int interval = 5000;
            String intervalString = Engine.properties.getProperty("atavism.log_proxy_histograms_interval");
            if (intervalString != null) {
               int newInterval = Integer.parseInt(intervalString);
               if (newInterval > 0) {
                  interval = newInterval;
               }
            }

            this.proxyQueueHistogram = new TimeHistogram("TimeInQ", interval);
            this.proxyCallbackHistogram = new TimeHistogram("TimeInCallback", interval);
            this.countLogger.start();
         }

         this.filteredProps = new HashSet();
         this.playerSpecificProps = new HashSet();
         this.cachedPlayerSpecificFilterProps = new HashSet();
         this.addFilteredProperty("inv.bag");
         this.addFilteredProperty(":loc");
         this.addFilteredProperty("masterOid");
         this.addFilteredProperty("agisobj.basedc");
         this.addFilteredProperty("aoobj.dc");
         this.addFilteredProperty("aoobj.followsterrainflag");
         this.addFilteredProperty("aoobj.perceiver");
         this.addFilteredProperty("aoobj.scale");
         this.addFilteredProperty("aoobj.mobflag");
         this.addFilteredProperty("aoobj.structflag");
         this.addFilteredProperty("aoobj.userflag");
         this.addFilteredProperty("aoobj.itemflag");
         this.addFilteredProperty("aoobj.lightflag");
         this.addFilteredProperty("namespace");
         this.addFilteredProperty("regenEffectMap");
         this.addFilteredProperty(WorldManagerClient.MOB_PATH_PROPERTY);
         this.addFilteredProperty(WorldManagerClient.TEMPL_SOUND_DATA_LIST);
         this.addFilteredProperty(WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
         this.addFilteredProperty("instanceStack");
         this.addFilteredProperty("currentInstanceName");
         this.addFilteredProperty("ignored_oids");
         this.registerHooks();
         atavism.server.plugins.ProxyPlugin.PluginMessageCallback pluginMessageCallback = new atavism.server.plugins.ProxyPlugin.PluginMessageCallback(this);
         MessageTypeFilter filter = new MessageTypeFilter();
         filter.addType(WorldManagerClient.MSG_TYPE_SYS_CHAT);
         Engine.getAgent().createSubscription(filter, pluginMessageCallback);
         LinkedList<MessageType> types = new LinkedList();
         types.add(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO);
         types.add(WorldManagerClient.MSG_TYPE_ANIMATION);
         types.add(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT);
         types.add(WorldManagerClient.MSG_TYPE_DETACH);
         types.add(PropertyMessage.MSG_TYPE_PROPERTY);
         types.add(ChatClient.MSG_TYPE_COM);
         types.add(SocialClient.MSG_TYPE_BLOCK_LIST);
         types.add(CombatClient.MSG_TYPE_DAMAGE);
         types.add(WorldManagerClient.MSG_TYPE_UPDATEWNODE);
         types.add(WorldManagerClient.MSG_TYPE_MOB_PATH);
         types.add(WorldManagerClient.MSG_TYPE_WNODECORRECT);
         types.add(WorldManagerClient.MSG_TYPE_ORIENT);
         types.add(WorldManagerClient.MSG_TYPE_SOUND);
         types.add(AnimationClient.MSG_TYPE_INVOKE_EFFECT);
         types.add(WorldManagerClient.MSG_TYPE_EXTENSION);
         types.add(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
         types.add(InventoryClient.MSG_TYPE_INV_UPDATE);
         types.add(CombatClient.MSG_TYPE_ABILITY_STATUS);
         types.add(CombatClient.MSG_TYPE_ABILITY_UPDATE);
         types.add(WorldManagerClient.MSG_TYPE_FOG);
         types.add(WorldManagerClient.MSG_TYPE_ROAD);
         types.add(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT);
         types.add(WorldManagerClient.MSG_TYPE_SET_AMBIENT);
         types.add(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY);
         types.add(WorldManagerClient.MSG_TYPE_FREE_OBJECT);
         types.add(MSG_TYPE_VOICE_PARMS);
         types.add(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
         types.add(MSG_TYPE_GET_MATCHING_PLAYERS);
         types.add(MSG_TYPE_ADD_STATIC_PERCEPTION);
         types.add(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
         if (this.extraPlayerMessageTypes != null) {
            types.addAll(this.extraPlayerMessageTypes);
         }

         this.perceptionFilter = new PerceptionFilter(types, true);
         PerceptionTrigger perceptionTrigger = new PerceptionTrigger();
         this.perceptionSubId = Engine.getAgent().createSubscription(this.perceptionFilter, this.playerMessageCallback, 0, perceptionTrigger);
         types.clear();
         types.add(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ);
         types.add(MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
         types.add(MSG_TYPE_GET_PLAYER_LOGIN_STATUS);
         types.add(MSG_TYPE_LOGOUT_PLAYER);
         this.responderFilter = new PerceptionFilter(types);
         this.responderSubId = Engine.getAgent().createSubscription(this.responderFilter, this.playerMessageCallback, 8);
         this.responderFilter2 = new PerceptionFilter();
         this.responderSubId2 = Engine.getAgent().createSubscription(this.responderFilter2, this, 8);
         types.clear();
         types.add(Management.MSG_TYPE_GET_PLUGIN_STATUS);
         Engine.getAgent().createSubscription(new MessageTypeFilter(types), pluginMessageCallback, 8);
         MessageTypeFilter filter3 = new MessageTypeFilter();
         filter3.addType(MSG_TYPE_ACCOUNT_LOGIN);
         Engine.getAgent().createSubscription(filter3, this);
         String log_rdp_counters = Engine.getProperty("atavism.log_rdp_counters");
         if (log_rdp_counters == null || log_rdp_counters.equals("false")) {
            RDPServer.setCounterLogging(false);
         }

         RDPServer.startRDPServer();
         this.initializeVoiceServerInformation();
         this.registerExtensionSubtype("voice_parms", MSG_TYPE_VOICE_PARMS);
         this.registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
         this.registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
         this.registerExtensionSubtype("ao.UPDATE_PLAYER_IGNORE_LIST", MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
         this.registerExtensionSubtype("ao.GET_MATCHING_PLAYERS", MSG_TYPE_GET_MATCHING_PLAYERS);
         this.registerExtensionSubtype("ao.PLAYER_IGNORE_LIST_REQ", MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
         Log.debug("ProxyPlugin before bindAddress");
         InetSocketAddress bindAddress = this.getBindAddress();
         Log.debug("ProxyPlugin after bindAddress " + bindAddress.getHostName() + " " + bindAddress.getAddress() + " " + bindAddress.getPort());
         Log.debug("ProxyPlugin before server socket");
         int port = Integer.parseInt(Engine.getProperty("atavism.proxy.bindport").trim());
         Log.debug("Proxy: getBindAddress port=" + port);
         String agent_name = Engine.getAgent().getName();
         String[] an = agent_name.split("_");
         int agentId = Integer.parseInt(an[1]);
         port += agentId - 1;
         int rdpChannels = Integer.parseInt(Engine.properties.getProperty("atavism.proxy.rdp_channels", String.valueOf(128)));

         for(int i = 0; i < rdpChannels; ++i) {
            RDPServerSocket serverSocket = new RDPServerSocket();
            serverSocket.registerAcceptCallback(this);
            serverSocket.bind(port, serverSocketReceiveBufferSize);
            if (Log.loggingDebug) {
               Log.debug("BIND: binding for client tcp and rdp packets on port " + bindAddress.getPort() + " with rdpsocket: " + serverSocket.toString());
            }
         }

         Log.debug("BIND: bound server socket");
         this.clientTCPMessageIO = ClientTCPMessageIO.setup(bindAddress, this, this);
         Log.debug("BIND: setup clientTCPMessage");
         this.clientTCPMessageIO.start("ClientIO");
         Log.debug("BIND: started clientTCPMessage");
         InetSocketAddress externalAddress = this.getExternalAddress(bindAddress);
         Log.debug("BIND: got external Address " + externalAddress.getHostName() + " " + externalAddress.getAddress() + " " + externalAddress.getPort());
         this.setPluginInfo("host=" + Engine.getProperty("atavism.proxy.externaladdress") + ",port=" + externalAddress.getPort());
         Log.debug("Registering proxy plugin");
         Engine.registerStatusReportingPlugin(this);
         Log.debug("Proxy: activation done");
         this.runCheck();
         Gauge.builder("event_qq_size", new 1(this)).register(Prometheus.registry());
         Gauge.builder("message_qq_size", new 2(this)).register(Prometheus.registry());
         Gauge.builder("message_qq_unqueued_size", new 3(this)).register(Prometheus.registry());
      } catch (Exception var16) {
         throw new AORuntimeException("activate failed", var16);
      }
   }

Код:
this.runCheck();
ну и да, декомпил кривой)
 
предполагаю что смотреть нужно где идёт вызов функции
вот здесь
Java:
public void onActivate() {
      try {
         PacketAggregator.initializeAggregation(Engine.getProperties());
         String logProxyHistograms = Engine.properties.getProperty("atavism.log_proxy_histograms");
         if (logProxyHistograms != null && logProxyHistograms.equals("true")) {
            int interval = 5000;
            String intervalString = Engine.properties.getProperty("atavism.log_proxy_histograms_interval");
            if (intervalString != null) {
               int newInterval = Integer.parseInt(intervalString);
               if (newInterval > 0) {
                  interval = newInterval;
               }
            }

            this.proxyQueueHistogram = new TimeHistogram("TimeInQ", interval);
            this.proxyCallbackHistogram = new TimeHistogram("TimeInCallback", interval);
            this.countLogger.start();
         }

         this.filteredProps = new HashSet();
         this.playerSpecificProps = new HashSet();
         this.cachedPlayerSpecificFilterProps = new HashSet();
         this.addFilteredProperty("inv.bag");
         this.addFilteredProperty(":loc");
         this.addFilteredProperty("masterOid");
         this.addFilteredProperty("agisobj.basedc");
         this.addFilteredProperty("aoobj.dc");
         this.addFilteredProperty("aoobj.followsterrainflag");
         this.addFilteredProperty("aoobj.perceiver");
         this.addFilteredProperty("aoobj.scale");
         this.addFilteredProperty("aoobj.mobflag");
         this.addFilteredProperty("aoobj.structflag");
         this.addFilteredProperty("aoobj.userflag");
         this.addFilteredProperty("aoobj.itemflag");
         this.addFilteredProperty("aoobj.lightflag");
         this.addFilteredProperty("namespace");
         this.addFilteredProperty("regenEffectMap");
         this.addFilteredProperty(WorldManagerClient.MOB_PATH_PROPERTY);
         this.addFilteredProperty(WorldManagerClient.TEMPL_SOUND_DATA_LIST);
         this.addFilteredProperty(WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
         this.addFilteredProperty("instanceStack");
         this.addFilteredProperty("currentInstanceName");
         this.addFilteredProperty("ignored_oids");
         this.registerHooks();
         atavism.server.plugins.ProxyPlugin.PluginMessageCallback pluginMessageCallback = new atavism.server.plugins.ProxyPlugin.PluginMessageCallback(this);
         MessageTypeFilter filter = new MessageTypeFilter();
         filter.addType(WorldManagerClient.MSG_TYPE_SYS_CHAT);
         Engine.getAgent().createSubscription(filter, pluginMessageCallback);
         LinkedList<MessageType> types = new LinkedList();
         types.add(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO);
         types.add(WorldManagerClient.MSG_TYPE_ANIMATION);
         types.add(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT);
         types.add(WorldManagerClient.MSG_TYPE_DETACH);
         types.add(PropertyMessage.MSG_TYPE_PROPERTY);
         types.add(ChatClient.MSG_TYPE_COM);
         types.add(SocialClient.MSG_TYPE_BLOCK_LIST);
         types.add(CombatClient.MSG_TYPE_DAMAGE);
         types.add(WorldManagerClient.MSG_TYPE_UPDATEWNODE);
         types.add(WorldManagerClient.MSG_TYPE_MOB_PATH);
         types.add(WorldManagerClient.MSG_TYPE_WNODECORRECT);
         types.add(WorldManagerClient.MSG_TYPE_ORIENT);
         types.add(WorldManagerClient.MSG_TYPE_SOUND);
         types.add(AnimationClient.MSG_TYPE_INVOKE_EFFECT);
         types.add(WorldManagerClient.MSG_TYPE_EXTENSION);
         types.add(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
         types.add(InventoryClient.MSG_TYPE_INV_UPDATE);
         types.add(CombatClient.MSG_TYPE_ABILITY_STATUS);
         types.add(CombatClient.MSG_TYPE_ABILITY_UPDATE);
         types.add(WorldManagerClient.MSG_TYPE_FOG);
         types.add(WorldManagerClient.MSG_TYPE_ROAD);
         types.add(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT);
         types.add(WorldManagerClient.MSG_TYPE_SET_AMBIENT);
         types.add(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY);
         types.add(WorldManagerClient.MSG_TYPE_FREE_OBJECT);
         types.add(MSG_TYPE_VOICE_PARMS);
         types.add(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
         types.add(MSG_TYPE_GET_MATCHING_PLAYERS);
         types.add(MSG_TYPE_ADD_STATIC_PERCEPTION);
         types.add(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
         if (this.extraPlayerMessageTypes != null) {
            types.addAll(this.extraPlayerMessageTypes);
         }

         this.perceptionFilter = new PerceptionFilter(types, true);
         PerceptionTrigger perceptionTrigger = new PerceptionTrigger();
         this.perceptionSubId = Engine.getAgent().createSubscription(this.perceptionFilter, this.playerMessageCallback, 0, perceptionTrigger);
         types.clear();
         types.add(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ);
         types.add(MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
         types.add(MSG_TYPE_GET_PLAYER_LOGIN_STATUS);
         types.add(MSG_TYPE_LOGOUT_PLAYER);
         this.responderFilter = new PerceptionFilter(types);
         this.responderSubId = Engine.getAgent().createSubscription(this.responderFilter, this.playerMessageCallback, 8);
         this.responderFilter2 = new PerceptionFilter();
         this.responderSubId2 = Engine.getAgent().createSubscription(this.responderFilter2, this, 8);
         types.clear();
         types.add(Management.MSG_TYPE_GET_PLUGIN_STATUS);
         Engine.getAgent().createSubscription(new MessageTypeFilter(types), pluginMessageCallback, 8);
         MessageTypeFilter filter3 = new MessageTypeFilter();
         filter3.addType(MSG_TYPE_ACCOUNT_LOGIN);
         Engine.getAgent().createSubscription(filter3, this);
         String log_rdp_counters = Engine.getProperty("atavism.log_rdp_counters");
         if (log_rdp_counters == null || log_rdp_counters.equals("false")) {
            RDPServer.setCounterLogging(false);
         }

         RDPServer.startRDPServer();
         this.initializeVoiceServerInformation();
         this.registerExtensionSubtype("voice_parms", MSG_TYPE_VOICE_PARMS);
         this.registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
         this.registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
         this.registerExtensionSubtype("ao.UPDATE_PLAYER_IGNORE_LIST", MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
         this.registerExtensionSubtype("ao.GET_MATCHING_PLAYERS", MSG_TYPE_GET_MATCHING_PLAYERS);
         this.registerExtensionSubtype("ao.PLAYER_IGNORE_LIST_REQ", MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
         Log.debug("ProxyPlugin before bindAddress");
         InetSocketAddress bindAddress = this.getBindAddress();
         Log.debug("ProxyPlugin after bindAddress " + bindAddress.getHostName() + " " + bindAddress.getAddress() + " " + bindAddress.getPort());
         Log.debug("ProxyPlugin before server socket");
         int port = Integer.parseInt(Engine.getProperty("atavism.proxy.bindport").trim());
         Log.debug("Proxy: getBindAddress port=" + port);
         String agent_name = Engine.getAgent().getName();
         String[] an = agent_name.split("_");
         int agentId = Integer.parseInt(an[1]);
         port += agentId - 1;
         int rdpChannels = Integer.parseInt(Engine.properties.getProperty("atavism.proxy.rdp_channels", String.valueOf(128)));

         for(int i = 0; i < rdpChannels; ++i) {
            RDPServerSocket serverSocket = new RDPServerSocket();
            serverSocket.registerAcceptCallback(this);
            serverSocket.bind(port, serverSocketReceiveBufferSize);
            if (Log.loggingDebug) {
               Log.debug("BIND: binding for client tcp and rdp packets on port " + bindAddress.getPort() + " with rdpsocket: " + serverSocket.toString());
            }
         }

         Log.debug("BIND: bound server socket");
         this.clientTCPMessageIO = ClientTCPMessageIO.setup(bindAddress, this, this);
         Log.debug("BIND: setup clientTCPMessage");
         this.clientTCPMessageIO.start("ClientIO");
         Log.debug("BIND: started clientTCPMessage");
         InetSocketAddress externalAddress = this.getExternalAddress(bindAddress);
         Log.debug("BIND: got external Address " + externalAddress.getHostName() + " " + externalAddress.getAddress() + " " + externalAddress.getPort());
         this.setPluginInfo("host=" + Engine.getProperty("atavism.proxy.externaladdress") + ",port=" + externalAddress.getPort());
         Log.debug("Registering proxy plugin");
         Engine.registerStatusReportingPlugin(this);
         Log.debug("Proxy: activation done");
         this.runCheck();
         Gauge.builder("event_qq_size", new 1(this)).register(Prometheus.registry());
         Gauge.builder("message_qq_size", new 2(this)).register(Prometheus.registry());
         Gauge.builder("message_qq_unqueued_size", new 3(this)).register(Prometheus.registry());
      } catch (Exception var16) {
         throw new AORuntimeException("activate failed", var16);
      }
   }

Код:
this.runCheck();
ну и да, декомпил кривой)
я хе как правильно декомпил делаТь)
 
не ну код читаем, просто нужно некоторые функции восстанавливать, там где у тебя varXX
Ток если бы я еще знал бы что там должно быть(

а ет декомпил ровный?
Java:
import atavism.agis.database.AccountDatabase;
import atavism.agis.database.ContentDatabase;
import atavism.agis.events.AbilityStatusEvent;
import atavism.agis.events.AbilityStatusMessage;
import atavism.agis.events.ConcludeQuest;
import atavism.agis.events.QuestResponse;
import atavism.agis.events.RequestQuestInfo;
import atavism.agis.plugins.AnimationClient;
import atavism.agis.plugins.ChatClient;
import atavism.agis.plugins.CombatClient;
import atavism.agis.plugins.DataLoggerClient;
import atavism.agis.plugins.QuestClient;
import atavism.agis.plugins.SocialClient;
import atavism.agis.util.EventMessageHelper;
import atavism.agis.util.HelperFunctions;
import atavism.management.Management;
import atavism.msgsys.FilterUpdate;
import atavism.msgsys.IFilter;
import atavism.msgsys.Message;
import atavism.msgsys.MessageCallback;
import atavism.msgsys.MessageTrigger;
import atavism.msgsys.MessageType;
import atavism.msgsys.MessageTypeFilter;
import atavism.msgsys.NoRecipientsException;
import atavism.msgsys.RPCTimeoutException;
import atavism.msgsys.ResponseCallback;
import atavism.msgsys.SubjectMessage;
import atavism.msgsys.TargetMessage;
import atavism.server.engine.BasicWorldNode;
import atavism.server.engine.Database;
import atavism.server.engine.Engine;
import atavism.server.engine.EnginePlugin;
import atavism.server.engine.Event;
import atavism.server.engine.Hook;
import atavism.server.engine.Namespace;
import atavism.server.engine.OID;
import atavism.server.events.ActivateItemEvent;
import atavism.server.events.AttachEvent;
import atavism.server.events.AuthorizedLoginEvent;
import atavism.server.events.AuthorizedLoginResponseEvent;
import atavism.server.events.AutoAttackEvent;
import atavism.server.events.ComEvent;
import atavism.server.events.CommandEvent;
import atavism.server.events.DirLocOrientEvent;
import atavism.server.events.ExtensionMessageEvent;
import atavism.server.events.FreeTerrainDecalEvent;
import atavism.server.events.LoadingStateEvent;
import atavism.server.events.LogoutEvent;
import atavism.server.events.ModelInfoEvent;
import atavism.server.events.NewLightEvent;
import atavism.server.events.NewTerrainDecalEvent;
import atavism.server.events.NotifyFreeObjectEvent;
import atavism.server.events.PlayerHaEvent;
import atavism.server.events.SceneLoadedEvent;
import atavism.server.events.WorldFileEvent;
import atavism.server.math.Point;
import atavism.server.messages.LoginMessage;
import atavism.server.messages.LogoutMessage;
import atavism.server.messages.PerceptionFilter;
import atavism.server.messages.PerceptionMessage;
import atavism.server.messages.PerceptionTrigger;
import atavism.server.messages.PropertyMessage;
import atavism.server.network.AOByteBuffer;
import atavism.server.network.ClientConnection;
import atavism.server.network.ClientTCPMessageIO;
import atavism.server.network.PacketAggregator;
import atavism.server.network.rdp.RDPServer;
import atavism.server.network.rdp.RDPServerSocket;
import atavism.server.objects.DisplayContext;
import atavism.server.objects.InstanceEntryCallback;
import atavism.server.objects.InstanceRestorePoint;
import atavism.server.objects.InstanceTemplate;
import atavism.server.objects.Light;
import atavism.server.objects.LightData;
import atavism.server.objects.ObjectType;
import atavism.server.objects.ObjectTypes;
import atavism.server.objects.OceanData;
import atavism.server.objects.Player;
import atavism.server.objects.PlayerManager;
import atavism.server.objects.ProxyExtensionHook;
import atavism.server.objects.ProxyLoginCallback;
import atavism.server.objects.SoundData;
import atavism.server.objects.Template;
import atavism.server.objects.TerrainDecalData;
import atavism.server.objects.World;
import atavism.server.plugins.ClientParameter;
import atavism.server.plugins.InstanceClient;
import atavism.server.plugins.InventoryClient;
import atavism.server.plugins.ObjectManagerClient;
import atavism.server.plugins.ProxyPlugin;
import atavism.server.plugins.WorldManagerClient;
import atavism.server.telemetry.Prometheus;
import atavism.server.util.AOMeter;
import atavism.server.util.AORuntimeException;
import atavism.server.util.Base64;
import atavism.server.util.CountLogger;
import atavism.server.util.DebugUtils;
import atavism.server.util.EncryptionHelper;
import atavism.server.util.LockFactory;
import atavism.server.util.Log;
import atavism.server.util.Logger;
import atavism.server.util.ObjectLockManager;
import atavism.server.util.SQCallback;
import atavism.server.util.SQThreadPool;
import atavism.server.util.SecureToken;
import atavism.server.util.SecureTokenManager;
import atavism.server.util.ServerVersion;
import atavism.server.util.SquareQueue;
import atavism.server.util.TimeHistogram;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.Timer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.function.Supplier;

public class ProxyPlugin extends EnginePlugin implements ClientConnection.AcceptCallback, ClientConnection.MessageCallback {
  private static int MESSAGE_QUEUE_THREADS = 16;
 
  private static int EVENT_QUEUE_THREADS = 16;
 
  private static int SLOW_EVENT_QUEUE_THREADS = 8;
 
  private static final int RDP_CHANNELS_COUNT = 128;
 
  public static final int PERCEPTION_GAIN_THRESHOLD = 20;
 
  CountLogger countLogger;
 
  CountLogger.Counter countMsgPerception;
 
  CountLogger.Counter countMsgPerceptionGain;
 
  CountLogger.Counter countMsgPerceptionLost;
 
  CountLogger.Counter countMsgUpdateWNodeIn;
 
  CountLogger.Counter countMsgUpdateWNodeOut;
 
  CountLogger.Counter countMsgPropertyIn;
 
  CountLogger.Counter countMsgPropertyOut;
 
  CountLogger.Counter countMsgTargetedProperty;
 
  CountLogger.Counter countMsgWNodeCorrectIn;
 
  CountLogger.Counter countMsgWNodeCorrectOut;
 
  CountLogger.Counter countMsgMobPathIn;
 
  CountLogger.Counter countMsgMobPathOut;
 
  public ProxyPlugin() {
    super(getPluginName(), null);
    this.countLogger = new CountLogger("ProxyMsg", 5000, 2);
    this.commandMapLock = LockFactory.makeLock("CommandMapLock");
    this.commandMap = new HashMap<>();
    this.defaultCommandAccess = (CommandAccessCheck)new DefaultCommandAccess(null);
    this.messageQQ = new SquareQueue("Message");
    this.messageThreadPool = null;
    this.eventQQ = new SquareQueue("Event");
    this.eventThreadPool = null;
    this.slowEventQQ = new SquareQueue("SlowEvent");
    this.slowEventThreadPool = null;
    this.clientMsgMeter = new AOMeter("ClientEventProcessorMeter");
    this.playerLastClientTime = new ConcurrentHashMap<>();
    this.playerLastServerTime = new ConcurrentHashMap<>();
    this.playerFirstSpeedHackTime = new ConcurrentHashMap<>();
    this.playerSpeedHackCount = new ConcurrentHashMap<>();
    this.defaultAllowClientToClientMessage = false;
    this.extensionMessageRegistry = new HashMap<>();
    this.logoutExecutor = Executors.newCachedThreadPool();
    this.playerMessageCallback = new PlayerMessageCallback(this);
    this.playerManager = new PlayerManager();
    this.playersOnlineList = new ConcurrentHashMap<>();
    this.playersOnlineOnProxy = new ConcurrentHashMap<>();
    this.proxyQueueHistogram = null;
    this.proxyCallbackHistogram = null;
    this.extraPlayerMessageTypes = null;
    this.proxyLoginCallback = (ProxyLoginCallback)new DefaultProxyLoginCallback(null);
    this.instanceEntryCallback = (InstanceEntryCallback)new DefaultInstanceEntryCallback(null);
    this.instanceEntryCount = 0;
    this.chatSentCount = 0;
    this.privateChatSentCount = 0;
    this.serverCapabilitiesSentToClient = "DirLocOrient";
    this.capacityError = "Login Failed: Servers at capacity, please try again later.";
    this.tokenError = "Login Failed: Secure token invalid.";
    this.clientTCPMessageIO = null;
    this.adminSet = new HashSet<>();
    this.clientConnections = new ConcurrentHashMap<>();
    this.filteredProps = null;
    this.playerSpecificProps = null;
    this.cachedPlayerSpecificFilterProps = null;
    this.serverVersion = null;
    this.extensionHooks = new HashMap<>();
    this.connectionLimit = 0;
    this.devMode = true;
    setPluginType("Proxy");
    this.serverVersion = "10.7.0 " + ServerVersion.getBuildNumber();
    String MessageQueueThreadPoolSize = Engine.properties.getProperty("atavism.proxy.MessageQueueThreadPoolSize");
    if (MessageQueueThreadPoolSize != null)
      try {
        int v = Integer.parseInt(MessageQueueThreadPoolSize);
        MESSAGE_QUEUE_THREADS = v;
      } catch (NumberFormatException e) {
        e.printStackTrace();
        Log.exception(e);
      } 
    String EventQueueThreadPoolSize = Engine.properties.getProperty("atavism.proxy.EventQueueThreadPoolSize");
    if (EventQueueThreadPoolSize != null)
      try {
        int v = Integer.parseInt(EventQueueThreadPoolSize);
        EVENT_QUEUE_THREADS = v;
      } catch (NumberFormatException e) {
        e.printStackTrace();
        Log.exception(e);
      } 
    String proxy_concurrent_logins = Engine.properties.getProperty("atavism.proxy.ConcurrentLogins");
    if (proxy_concurrent_logins != null)
      try {
        int v = Integer.parseInt(proxy_concurrent_logins);
        SLOW_EVENT_QUEUE_THREADS = v;
      } catch (NumberFormatException e) {
        e.printStackTrace();
        Log.exception(e);
      } 
    this.messageThreadPool = new SQThreadPool(this.messageQQ, (SQCallback)new MessageCallback(this, this), MESSAGE_QUEUE_THREADS);
    this.eventThreadPool = new SQThreadPool(this.eventQQ, (SQCallback)new EventCallback(this), EVENT_QUEUE_THREADS);
    this.slowEventThreadPool = new SQThreadPool(this.slowEventQQ, (SQCallback)new EventCallback(this), SLOW_EVENT_QUEUE_THREADS);
    this.countMsgPerception = this.countLogger.addCounter("ao.PERCEPTION_INFO");
    this.countMsgPerceptionGain = this.countLogger.addCounter("Perception.gain");
    this.countMsgPerceptionLost = this.countLogger.addCounter("Perception.lost");
    this.countMsgUpdateWNodeIn = this.countLogger.addCounter("ao.UPDATEWNODE.in");
    this.countMsgUpdateWNodeOut = this.countLogger.addCounter("ao.UPDATEWNODE.out");
    this.countMsgPropertyIn = this.countLogger.addCounter("ao.PROPERTY.in");
    this.countMsgPropertyOut = this.countLogger.addCounter("ao.PROPERTY.out");
    this.countMsgTargetedProperty = this.countLogger.addCounter("ao.TARGETED_PROPERTY");
    this.countMsgWNodeCorrectIn = this.countLogger.addCounter("ao.WNODECORRECT.in");
    this.countMsgWNodeCorrectOut = this.countLogger.addCounter("ao.WNODECORRECT.out");
    this.countMsgMobPathIn = this.countLogger.addCounter("ao.MOB_PATH.in");
    this.countMsgMobPathOut = this.countLogger.addCounter("ao.MOB_PATH.out");
    ContentDatabase ctDB = new ContentDatabase(false);
    String _silenceTimeout = ctDB.loadGameSetting("PLAYER_SILENCE_TIMEOUT");
    if (_silenceTimeout != null)
      silenceTimeout = Integer.parseInt(_silenceTimeout);
    this.aDB = new AccountDatabase(true);
    addProxyExtensionHook("ao.heartbeat", (ProxyExtensionHook)new PlayerHeartbeat(null));
    (new Thread((Runnable)new PlayerTimeout(this, null), "PlayerTimeout")).start();
  }
 
  private static String getPluginName() {
    String proxyPluginName;
    try {
      proxyPluginName = Engine.getAgent().getDomainClient().allocName("PLUGIN", "Proxy#");
    } catch (IOException e) {
      throw new AORuntimeException("Could not allocate proxy plugin name", e);
    }
    return proxyPluginName;
  }
 
  public static boolean isOnBlockList(OID subject, OID target) {
    WorldManagerClient.ExtensionMessage message = new WorldManagerClient.ExtensionMessage(SocialClient.MSG_TYPE_IS_ON_BLOCK_LIST, "ao.IS_ON_BLOCK_LIST", subject);
    message.setProperty("targetOid", (Serializable)target);
    return Engine.getAgent().sendRPCReturnBoolean((Message)message).booleanValue();
  }
 
  public boolean isDevMode() {
    return this.devMode;
  }
 
  public void setDevMode(boolean mode) {
    this.devMode = mode;
  }
 
  public List<MessageType> getExtraPlayerMessageTypes() {
    return this.extraPlayerMessageTypes;
  }
 
  public void setExtraPlayerMessageTypes(List<MessageType> extraPlayerMessageTypes) {
    this.extraPlayerMessageTypes = extraPlayerMessageTypes;
  }
 
  public void addExtraPlayerMessageType(MessageType messageType) {
    if (this.extraPlayerMessageTypes == null)
      this.extraPlayerMessageTypes = new LinkedList<>();
    this.extraPlayerMessageTypes.add(messageType);
  }
 
  public void addExtraPlayerExtensionMessageType(MessageType messageType) {
    addExtraPlayerMessageType(messageType);
    getHookManager().addHook(messageType, (Hook)new ExtensionHook(this));
  }
 
  public void addProxyExtensionHook(String subType, ProxyExtensionHook hook) {
    synchronized (this.extensionHooks) {
      List<ProxyExtensionHook> hookList = this.extensionHooks.get(subType);
      if (hookList == null) {
        hookList = new ArrayList<>();
        this.extensionHooks.put(subType, hookList);
      }
      hookList.add(hook);
    }
  }
 
  public Map<String, List<ProxyExtensionHook>> getProxyExtensionHooks(String subType) {
    return this.extensionHooks;
  }
 
  public void onActivate() {
    try {
      PacketAggregator.initializeAggregation(Engine.getProperties());
      String logProxyHistograms = Engine.properties.getProperty("atavism.log_proxy_histograms");
      if (logProxyHistograms != null && logProxyHistograms.equals("true")) {
        int interval = 5000;
        String intervalString = Engine.properties.getProperty("atavism.log_proxy_histograms_interval");
        if (intervalString != null) {
          int newInterval = Integer.parseInt(intervalString);
          if (newInterval > 0)
            interval = newInterval;
        }
        this.proxyQueueHistogram = new TimeHistogram("TimeInQ", Integer.valueOf(interval));
        this.proxyCallbackHistogram = new TimeHistogram("TimeInCallback", Integer.valueOf(interval));
        this.countLogger.start();
      }
      this.filteredProps = new HashSet<>();
      this.playerSpecificProps = new HashSet<>();
      this.cachedPlayerSpecificFilterProps = new HashSet<>();
      addFilteredProperty("inv.bag");
      addFilteredProperty(":loc");
      addFilteredProperty("masterOid");
      addFilteredProperty("agisobj.basedc");
      addFilteredProperty("aoobj.dc");
      addFilteredProperty("aoobj.followsterrainflag");
      addFilteredProperty("aoobj.perceiver");
      addFilteredProperty("aoobj.scale");
      addFilteredProperty("aoobj.mobflag");
      addFilteredProperty("aoobj.structflag");
      addFilteredProperty("aoobj.userflag");
      addFilteredProperty("aoobj.itemflag");
      addFilteredProperty("aoobj.lightflag");
      addFilteredProperty("namespace");
      addFilteredProperty("regenEffectMap");
      addFilteredProperty(WorldManagerClient.MOB_PATH_PROPERTY);
      addFilteredProperty(WorldManagerClient.TEMPL_SOUND_DATA_LIST);
      addFilteredProperty(WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
      addFilteredProperty("instanceStack");
      addFilteredProperty("currentInstanceName");
      addFilteredProperty("ignored_oids");
      registerHooks();
      PluginMessageCallback pluginMessageCallback = new PluginMessageCallback(this);
      MessageTypeFilter filter = new MessageTypeFilter();
      filter.addType(WorldManagerClient.MSG_TYPE_SYS_CHAT);
      Engine.getAgent().createSubscription((IFilter)filter, (MessageCallback)pluginMessageCallback);
      LinkedList<MessageType> types = new LinkedList<>();
      types.add(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO);
      types.add(WorldManagerClient.MSG_TYPE_ANIMATION);
      types.add(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT);
      types.add(WorldManagerClient.MSG_TYPE_DETACH);
      types.add(PropertyMessage.MSG_TYPE_PROPERTY);
      types.add(ChatClient.MSG_TYPE_COM);
      types.add(SocialClient.MSG_TYPE_BLOCK_LIST);
      types.add(CombatClient.MSG_TYPE_DAMAGE);
      types.add(WorldManagerClient.MSG_TYPE_UPDATEWNODE);
      types.add(WorldManagerClient.MSG_TYPE_MOB_PATH);
      types.add(WorldManagerClient.MSG_TYPE_WNODECORRECT);
      types.add(WorldManagerClient.MSG_TYPE_ORIENT);
      types.add(WorldManagerClient.MSG_TYPE_SOUND);
      types.add(AnimationClient.MSG_TYPE_INVOKE_EFFECT);
      types.add(WorldManagerClient.MSG_TYPE_EXTENSION);
      types.add(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
      types.add(InventoryClient.MSG_TYPE_INV_UPDATE);
      types.add(CombatClient.MSG_TYPE_ABILITY_STATUS);
      types.add(CombatClient.MSG_TYPE_ABILITY_UPDATE);
      types.add(WorldManagerClient.MSG_TYPE_FOG);
      types.add(WorldManagerClient.MSG_TYPE_ROAD);
      types.add(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT);
      types.add(WorldManagerClient.MSG_TYPE_SET_AMBIENT);
      types.add(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY);
      types.add(WorldManagerClient.MSG_TYPE_FREE_OBJECT);
      types.add(MSG_TYPE_VOICE_PARMS);
      types.add(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
      types.add(MSG_TYPE_GET_MATCHING_PLAYERS);
      types.add(MSG_TYPE_ADD_STATIC_PERCEPTION);
      types.add(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
      if (this.extraPlayerMessageTypes != null)
        types.addAll(this.extraPlayerMessageTypes);
      this.perceptionFilter = new PerceptionFilter(types, true);
      PerceptionTrigger perceptionTrigger = new PerceptionTrigger();
      this.perceptionSubId = Engine.getAgent().createSubscription((IFilter)this.perceptionFilter, (MessageCallback)this.playerMessageCallback, 0, (MessageTrigger)perceptionTrigger);
      types.clear();
      types.add(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ);
      types.add(MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
      types.add(MSG_TYPE_GET_PLAYER_LOGIN_STATUS);
      types.add(MSG_TYPE_LOGOUT_PLAYER);
      this.responderFilter = new PerceptionFilter(types);
      this.responderSubId = Engine.getAgent().createSubscription((IFilter)this.responderFilter, (MessageCallback)this.playerMessageCallback, 8);
      this.responderFilter2 = new PerceptionFilter();
      this.responderSubId2 = Engine.getAgent().createSubscription((IFilter)this.responderFilter2, (MessageCallback)this, 8);
      types.clear();
      types.add(Management.MSG_TYPE_GET_PLUGIN_STATUS);
      Engine.getAgent().createSubscription((IFilter)new MessageTypeFilter(types), (MessageCallback)pluginMessageCallback, 8);
      MessageTypeFilter filter3 = new MessageTypeFilter();
      filter3.addType(MSG_TYPE_ACCOUNT_LOGIN);
      Engine.getAgent().createSubscription((IFilter)filter3, (MessageCallback)this);
      String log_rdp_counters = Engine.getProperty("atavism.log_rdp_counters");
      if (log_rdp_counters == null || log_rdp_counters.equals("false"))
        RDPServer.setCounterLogging(false);
      RDPServer.startRDPServer();
      initializeVoiceServerInformation();
      registerExtensionSubtype("voice_parms", MSG_TYPE_VOICE_PARMS);
      registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
      registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
      registerExtensionSubtype("ao.UPDATE_PLAYER_IGNORE_LIST", MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
      registerExtensionSubtype("ao.GET_MATCHING_PLAYERS", MSG_TYPE_GET_MATCHING_PLAYERS);
      registerExtensionSubtype("ao.PLAYER_IGNORE_LIST_REQ", MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
      Log.debug("ProxyPlugin before bindAddress");
      InetSocketAddress bindAddress = getBindAddress();
      Log.debug("ProxyPlugin after bindAddress " + bindAddress.getHostName() + " " + bindAddress.getAddress() + " " + bindAddress.getPort());
      Log.debug("ProxyPlugin before server socket");
      int port = Integer.parseInt(Engine.getProperty("atavism.proxy.bindport").trim());
      Log.debug("Proxy: getBindAddress port=" + port);
      String agent_name = Engine.getAgent().getName();
      String[] an = agent_name.split("_");
      int agentId = Integer.parseInt(an[1]);
      port += agentId - 1;
      int rdpChannels = Integer.parseInt(Engine.properties.getProperty("atavism.proxy.rdp_channels", String.valueOf(128)));
      for (int i = 0; i < rdpChannels; i++) {
        RDPServerSocket serverSocket = new RDPServerSocket();
        serverSocket.registerAcceptCallback(this);
        serverSocket.bind(Integer.valueOf(port), serverSocketReceiveBufferSize);
        if (Log.loggingDebug)
          Log.debug("BIND: binding for client tcp and rdp packets on port " + bindAddress.getPort() + " with rdpsocket: " + serverSocket.toString());
      }
      Log.debug("BIND: bound server socket");
      this.clientTCPMessageIO = ClientTCPMessageIO.setup(bindAddress, this, this);
      Log.debug("BIND: setup clientTCPMessage");
      this.clientTCPMessageIO.start("ClientIO");
      Log.debug("BIND: started clientTCPMessage");
      InetSocketAddress externalAddress = getExternalAddress(bindAddress);
      Log.debug("BIND: got external Address " + externalAddress.getHostName() + " " + externalAddress.getAddress() + " " + externalAddress.getPort());
      setPluginInfo("host=" + Engine.getProperty("atavism.proxy.externaladdress") + ",port=" + externalAddress.getPort());
      Log.debug("Registering proxy plugin");
      Engine.registerStatusReportingPlugin(this);
      Log.debug("Proxy: activation done");
      runCheck();
      Gauge.builder("event_qq_size", (Supplier)new Object(this)).register(Prometheus.registry());
      Gauge.builder("message_qq_size", (Supplier)new Object(this)).register(Prometheus.registry());
      Gauge.builder("message_qq_unqueued_size", (Supplier)new Object(this)).register(Prometheus.registry());
    } catch (Exception e) {
      throw new AORuntimeException("activate failed", e);
    }
  }
 
  private InetSocketAddress getBindAddress() throws IOException {
    int port;
    String propStr = Engine.getProperty("atavism.proxy.bindport");
    Log.debug("Proxy: getBindAddress propStr=" + propStr);
    if (propStr != null) {
      port = Integer.parseInt(propStr.trim());
      Log.debug("Proxy: getBindAddress port=" + port);
      String agent_name = Engine.getAgent().getName();
      String[] an = agent_name.split("_");
      int agentId = Integer.parseInt(an[1]);
      port += agentId - 1;
      Log.debug("Proxy: getBindAddress port=" + port);
    } else {
      port = Integer.parseInt(Engine.getProperty("atavism.proxyport").trim());
    }
    Log.debug("Proxy: getBindAddress port=" + port);
    propStr = Engine.getProperty("atavism.proxy.bindaddress");
    Log.debug("Proxy: getBindAddress propStr=" + propStr + " " + Character.digit(propStr.charAt(0), 16) + " " + Character.digit(propStr.charAt(1), 16) + " " + Character.digit(propStr.charAt(2), 16) + " c=");
    int count = 0;
    if (propStr.contains("."))
      for (int i = 0; i < propStr.length(); i++) {
        if (propStr.charAt(i) == '.')
          count++;
      } 
    InetAddress address = null;
    InetAddress[] address2 = null;
    if (count != 3 || Character.digit(propStr.charAt(0), 10) != -1);
    if (propStr != null)
      try {
        address = InetAddress.getByName(propStr.trim());
        address2 = InetAddress.getAllByName(propStr.trim());
        for (InetAddress ai : address2)
          Log.debug("Proxy: getBindAddress address2=" + ai + " " + ai.getHostName() + " " + ai.getHostAddress());
        Log.debug("Proxy: getBindAddress address=" + address + " " + address.getHostName() + " " + address.getHostAddress());
      } catch (UnknownHostException e) {
        log.error("getBindAddress " + e.getMessage() + " " + e.getLocalizedMessage());
      } 
    Log.debug("Proxy: getBindAddress address=" + address + " " + address.getHostName() + " " + address.getAddress());
    return new InetSocketAddress(address, port);
  }
 
  private InetSocketAddress getExternalAddress(InetSocketAddress bindAddress) throws IOException {
    int port;
    InetAddress address;
    String propStr = Engine.getProperty("atavism.proxy.externalport");
    Log.debug("Proxy: getExternalAddress ext port propStr=" + propStr);
    if (propStr != null) {
      port = Integer.parseInt(propStr.trim());
    } else {
      port = bindAddress.getPort();
    }
    Log.debug("Proxy: getExternalAddress port=" + port);
    propStr = Engine.getProperty("atavism.proxy.externaladdress");
    Log.debug("Proxy: getExternalAddress ext addr propStr=" + propStr);
    if (propStr != null) {
      address = InetAddress.getByName(propStr.trim());
    } else {
      address = bindAddress.getAddress();
      Log.debug("Proxy: getExternalAddress else address=" + address);
      if (address.isAnyLocalAddress()) {
        address = InetAddress.getLocalHost();
        Log.debug("Proxy: getExternalAddress get local host address=" + address + " " + address.getHostName() + " " + address.getHostAddress());
      }
    }
    Log.debug("Proxy: getExternalAddress address=" + address + " " + address.getHostName() + " " + address.getAddress());
    return new InetSocketAddress(address, port);
  }
 
  private String howla() {
    String characters = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnoprstquwxyz123456789";
    String k = "";
    for (int i = 0; i < 14; i++) {
      Random random = new Random();
      k = k + characters.charAt(random.nextInt(characters.length() - 1));
    }
    return k;
  }
 
  private void runCheck() {
    String email = Engine.getProperty("atavism.licence.email");
    String licencekey = Engine.getProperty("atavism.licence.key");
    String proxy_id = Engine.getProperty("atavism.proxy.id");
    int num = 0;
    int proxyId = 0;
    try {
      if (proxy_id != null && proxy_id != "")
        proxyId = Integer.parseInt(proxy_id);
    } catch (NumberFormatException numberFormatException) {}
    String[] url = { "https://apanel.atavismonline.com/login/verifyserver.php", "https://licensing2.dragonsan.com:2443/login/verifyserver.php", "https://licensing1.atavismonline.com/login/verifyserver.php", "https://licensing.dragonsan.com/login/verifyserver.php", "https://licensing1.dragonsan.com/login/verifyserver.php", "https://licensing.atavismonline.com/login/verifyserver.php", "https://licensing2.atavismonline.com/login/verifyserver.php" };
    String resSor = howla();
    rck reCheck = new rck(this, resSor);
    Engine.getExecutor().scheduleAtFixedRate((Runnable)reCheck, 300L, 300L, TimeUnit.SECONDS);
    while (num < url.length) {
      boolean failed = false;
      try {
        String res = "";
        URL urlObj = new URL(url[num]);
        URLConnection lu = urlObj.openConnection();
        lu.setConnectTimeout(10000);
        String data = "email=" + URLEncoder.encode(email, "UTF-8") + "&licence=" + URLEncoder.encode(licencekey, "UTF-8") + "&ver=" + URLEncoder.encode("10.7.0", "UTF-8") + "&addr=" + URLEncoder.encode(Engine.getProperty("atavism.proxy.bindaddress"), "UTF-8") + "&sor=" + URLEncoder.encode(resSor, "UTF-8") + "&c=" + URLEncoder.encode("0", "UTF-8") + "&cp=" + this.playerManager.getPlayerCount() + " &pi=" + proxyId + "&build=" + URLEncoder.encode(ServerVersion.getBuildDate(), "UTF-8") + "&m=" + MaxConcurrentUsers;
        lu.setDoOutput(true);
        OutputStreamWriter wr = new OutputStreamWriter(lu.getOutputStream());
        wr.write(data);
        wr.flush();
        BufferedReader rd = new BufferedReader(new InputStreamReader(lu.getInputStream()));
        String line = "";
        while ((line = rd.readLine()) != null)
          res = res + line;
        wr.flush();
        wr.close();
        if (debugLic)
          System.out.println("\n" + url[num] + "\n" + res + "\n");
        res = HelperFunctions.readEncodedString(Base64.decode(res));
        String[] output = res.split(":");
        if (debugLic)
          System.out.println("\nsec: " + resSor + "\n s: " + HelperFunctions.readEncodedString(Base64.decode(output[2])) + "\n");
        if (EncryptionHelper.passwordMD5Check(output[0], getTemp()) && resSor.equals(HelperFunctions.readEncodedString(Base64.decode(output[2])))) {
          this.connectionLimit = Integer.parseInt(HelperFunctions.readEncodedString(Base64.decode(output[1])));
        } else {
          System.out.println("\nLicense verification failed");
          Log.error("License verification failed");
        }
        Log.debug("CONNECTOR: connections set to: " + this.connectionLimit);
      } catch (Exception e) {
        Log.error("CONNECTOR: failed verifying " + e);
        if (debugLic)
          System.out.println("\n" + url[num] + "\n" + e);
        num++;
        failed = true;
      }
      if (!failed)
        return;
    }
    System.out.println("\nLicense verification failed");
    Log.error("License verification failed");
    this.connectionLimit = 0;
  }
 
  public static boolean debugLic = false;
 
  protected Lock commandMapLock;
 
  Map<String, RegisteredCommand> commandMap;
 
  CommandAccessCheck defaultCommandAccess;
 
  SquareQueue<Player, Message> messageQQ;
 
  SQThreadPool messageThreadPool;
 
  private final SquareQueue<Player, Event> eventQQ;
 
  private SQThreadPool<Player, Event> eventThreadPool;
 
  private final SquareQueue<Player, Event> slowEventQQ;
 
  private SQThreadPool<Player, Event> slowEventThreadPool;
 
  AOMeter clientMsgMeter;
 
  protected ConcurrentHashMap<OID, Long> playerLastClientTime;
 
  protected ConcurrentHashMap<OID, Long> playerLastServerTime;
 
  protected ConcurrentHashMap<OID, Long> playerFirstSpeedHackTime;
 
  protected ConcurrentHashMap<OID, Long> playerSpeedHackCount;
 
  public boolean defaultAllowClientToClientMessage;
 
  protected HashMap<String, MessageType> extensionMessageRegistry;
 
  private final ExecutorService logoutExecutor;
 
  protected AccountDatabase aDB;
 
  protected PerceptionFilter perceptionFilter;
 
  protected long perceptionSubId;
 
  protected PerceptionFilter responderFilter;
 
  protected PerceptionFilter responderFilter2;
 
  protected long responderSubId;
 
  protected long responderSubId2;
 
  protected int clientPort;
 
  public Map<String, String> getStatusMap() {
    Map<String, String> status = new HashMap<>();
    status.put("players", Integer.toString(this.playerManager.getPlayerCount()));
    return status;
  }
 
  public void registerCommand(String command, CommandParser parser) {
    this.commandMapLock.lock();
    try {
      this.commandMap.put(command, new RegisteredCommand(parser, this.defaultCommandAccess));
    } finally {
      this.commandMapLock.unlock();
    }
  }
 
  public void registerCommand(String command, CommandParser parser, CommandAccessCheck access) {
    this.commandMapLock.lock();
    try {
      this.commandMap.put(command, new RegisteredCommand(parser, access));
    } finally {
      this.commandMapLock.unlock();
    }
  }
 
  void registerHooks() {
    log.debug("registering hooks");
    getHookManager().addHook(SocialClient.MSG_TYPE_BLOCK_LIST, (Hook)new BlockListHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT, (Hook)new DisplayContextHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_DETACH, (Hook)new DetachHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_ANIMATION, (Hook)new AnimationHook(this));
    getHookManager().addHook(AnimationClient.MSG_TYPE_INVOKE_EFFECT, (Hook)new InvokeEffectHook(this));
    getHookManager().addHook(PropertyMessage.MSG_TYPE_PROPERTY, (Hook)new PropertyHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_EXTENSION, (Hook)new ExtensionHook(this));
    getHookManager().addHook(CombatClient.MSG_TYPE_ABILITY_STATUS, (Hook)new AbilityStatusHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY, (Hook)new TargetedPropertyHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO, (Hook)new PerceptionHook(this));
    getHookManager().addHook(ChatClient.MSG_TYPE_COM, (Hook)new ComHook(this));
    getHookManager().addHook(CombatClient.MSG_TYPE_DAMAGE, (Hook)new DamageHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_SYS_CHAT, (Hook)new SysChatHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_UPDATEWNODE, (Hook)new UpdateWNodeHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_MOB_PATH, (Hook)new UpdateMobPathHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_WNODECORRECT, (Hook)new WNodeCorrectHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_ORIENT, (Hook)new OrientHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_SOUND, (Hook)new SoundHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_FOG, (Hook)new FogHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_ROAD, (Hook)new RoadHook(this));
    getHookManager().addHook(InventoryClient.MSG_TYPE_INV_UPDATE, (Hook)new InvUpdateHook(this));
    getHookManager().addHook(CombatClient.MSG_TYPE_ABILITY_UPDATE, (Hook)new AbilityUpdateHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT, (Hook)new NewDirLightHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_FREE_OBJECT, (Hook)new FreeObjectHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_SET_AMBIENT, (Hook)new SetAmbientHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_P2P_EXTENSION, (Hook)new P2PExtensionHook(this));
    getHookManager().addHook(MSG_TYPE_VOICE_PARMS, (Hook)new VoiceParmsHook(this));
    getHookManager().addHook(MSG_TYPE_PLAYER_PATH_REQ, (Hook)new PlayerPathReqHook(this));
    getHookManager().addHook(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ, (Hook)new InstanceEntryReqHook(this));
    getHookManager().addHook(Management.MSG_TYPE_GET_PLUGIN_STATUS, (Hook)new GetPluginStatusHook(this));
    getHookManager().addHook(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST, (Hook)new UpdatePlayerIgnoreListHook(this));
    getHookManager().addHook(MSG_TYPE_GET_MATCHING_PLAYERS, (Hook)new GetMatchingPlayersHook(this));
    getHookManager().addHook(MSG_TYPE_PLAYER_IGNORE_LIST_REQ, (Hook)new PlayerIgnoreListReqHook(this));
    getHookManager().addHook(MSG_TYPE_GET_PLAYER_LOGIN_STATUS, (Hook)new GetPlayerLoginStatusHook(this, null));
    getHookManager().addHook(MSG_TYPE_LOGOUT_PLAYER, (Hook)new LogoutPlayerHook(this, null));
    getHookManager().addHook(MSG_TYPE_ADD_STATIC_PERCEPTION, (Hook)new AddStaticPerceptionHook(this, null));
    getHookManager().addHook(MSG_TYPE_REMOVE_STATIC_PERCEPTION, (Hook)new RemoveStaticPerceptionHook(this, null));
    getHookManager().addHook(MSG_TYPE_ACCOUNT_LOGIN, (Hook)new AccountLoginHook(this, null));
  }
 
  void callEngineOnMessage(Message message, int flags) {
    handleMessage(message, flags);
  }
 
  protected void initializeVoiceServerInformation() {
    voiceServerHost = Engine.properties.getProperty("atavism.voiceserver");
    String s = Engine.properties.getProperty("atavism.voiceport");
    if (s != null)
      voiceServerPort = Integer.valueOf(Integer.parseInt(s));
    if (Log.loggingDebug)
      log.debug("initializeVoiceServerInformation: voiceServerHost " + voiceServerHost + ", voiceServerPort " + voiceServerPort);
  }
 
  public void acceptConnection(ClientConnection con) {
    Log.info("ProxyPlugin: CONNECTION remote=" + con);
    con.registerMessageCallback(this);
  }
 
  public void processPacket(ClientConnection con, AOByteBuffer buf) {
    try {
      long time1 = System.nanoTime();
      if (Log.loggingNet)
        if (ClientConnection.getLogMessageContents()) {
          Log.net("ProxyPlugin.processPacket: con " + con + ", length " + buf.limit() + ", packet " + DebugUtils.byteArrayToHexString(buf));
        } else {
          Log.net("ProxyPlugin.processPacket: con " + con + ", buf " + buf);
        } 
      Event event = Engine.getEventServer().parseBytes(buf, con);
      if (event == null) {
        Log.error("Engine: could not parse packet data, remote=" + con);
        return;
      }
      SquareQueue<Player, Event> qq = this.eventQQ;
      if (event instanceof AuthorizedLoginEvent)
        qq = this.slowEventQQ;
      Player player = (Player)con.getAssociation();
      if (player == null)
        if (event instanceof AuthorizedLoginEvent) {
          Log.info("ProxyPlugin: LOGIN_RECV remote=" + con + " playerOid=" + ((AuthorizedLoginEvent)event).getOid());
          player = new Player(((AuthorizedLoginEvent)event).getOid(), con);
        } else {
          Log.error("Cannot process event for connection with no player: " + con);
          return;
        } 
      this.playerManager.processEvent(player, event, qq);
      long time2 = System.nanoTime();
      Timer.builder("process_packet_time").tags(new String[] { "event", event.getClass().getSimpleName() }).publishPercentiles(new double[] { 0.9D }).register(Prometheus.registry()).record(Duration.ofNanos(time2 - time1));
    } catch (AORuntimeException e) {
      Log.exception("ProxyPlugin.processPacket caught exception", (Exception)e);
    }
  }
 
  public Set<OID> getPlayerOids() {
    List<Player> players = new ArrayList<>(this.playerManager.getPlayerCount());
    this.playerManager.getPlayers(players);
    Set<OID> result = new HashSet<>(players.size());
    for (Player player : players)
      result.add(player.getOid());
    return result;
  }
 
  public List<String> getPlayerNames() {
    List<Player> players = new ArrayList<>(this.playerManager.getPlayerCount());
    Log.debug("ProxyPlugin.getPlayerNames: count is " + this.playerManager.getPlayerCount());
    this.playerManager.getPlayers(players);
    List<String> result = new ArrayList<>(players.size());
    for (Player player : players)
      result.add(player.getName() + " " + player.getOid() + " " + getName());
    Collections.sort(result);
    return result;
  }
 
  public List<String> getAllPlayerNames() {
    Log.debug("ProxyPlugin.getAllPlayerNames: count is " + this.playersOnlineList.size());
    List<String> result = new ArrayList<>(this.playersOnlineList.size());
    HashMap<OID, String> plays = new HashMap<>();
    plays.putAll(this.playersOnlineList);
    for (OID player : plays.keySet())
      result.add((String)plays.get(player) + " " + player + " " + (String)this.playersOnlineOnProxy.get(player));
    Collections.sort(result);
    return result;
  }
 
  public List<Player> getPlayers() {
    List<Player> players = new ArrayList<>(this.playerManager.getPlayerCount());
    this.playerManager.getPlayers(players);
    return players;
  }
 
  public Player getPlayer(OID oid) {
    return this.playerManager.getPlayer(oid);
  }
 
  public void addPlayerMessage(Message message, Player player) {
    long start = System.nanoTime();
    message.setEnqueueTime();
    this.messageQQ.insert(player, message);
    long microseconds = System.nanoTime() - start;
  }
 
  public void addFilteredProperty(String filteredProperty) {
    this.filteredProps.add(filteredProperty);
    this.cachedPlayerSpecificFilterProps.add(filteredProperty);
  }
 
  public void addPlayerSpecificProperty(String filteredProperty) {
    this.playerSpecificProps.add(filteredProperty);
    this.cachedPlayerSpecificFilterProps.add(filteredProperty);
  }
 
  protected void recreatePlayerSpecificCache() {
    this.cachedPlayerSpecificFilterProps = new HashSet<>();
    this.cachedPlayerSpecificFilterProps.addAll(this.filteredProps);
    this.cachedPlayerSpecificFilterProps.addAll(this.playerSpecificProps);
  }
 
  protected boolean processLogin(ClientConnection con, AuthorizedLoginEvent loginEvent) {
    Prometheus.registry().counter("player_login_request", new String[0]).increment();
    OID playerOid = loginEvent.getOid();
    String version = loginEvent.getVersion();
    int nPlayers = this.playerManager.getPlayerCount();
    String[] clientVersionCapabilities = null;
    if (version != null && version.length() > 0)
      clientVersionCapabilities = version.split(",");
    LinkedList<String> clientCapabilities = new LinkedList<>();
    String clientVersion = "";
    if (clientVersionCapabilities != null && clientVersionCapabilities.length > 0) {
      clientVersion = clientVersionCapabilities[0];
      for (int i = 1; i < clientVersionCapabilities.length; i++)
        clientCapabilities.add(clientVersionCapabilities[i].trim());
    }
    int versionCompare = ServerVersion.compareVersionStrings(clientVersion, "10.7.0");
    if (versionCompare != 0) {
      Log.warn("processLogin: unsupported version " + clientVersion + " from player: " + playerOid);
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Unsupported client version", this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "unsupported_version" }).increment();
      return false;
    }
    if (!isAdmin(playerOid) || nPlayers >= this.connectionLimit) {
      Log.debug("processLogin: player is not admin");
      if (nPlayers >= MaxConcurrentUsers || nPlayers >= this.connectionLimit) {
        Log.warn("processLogin: too many users, failed for player: " + playerOid);
        AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, this.capacityError, this.serverVersion);
        con.send(authorizedLoginResponseEvent.toBytes());
        Prometheus.registry().counter("player_login_result", new String[] { "status", "too_many_users_" + String.valueOf(this.connectionLimit) }).increment();
        return false;
      }
    } else {
      Log.debug("processLogin: player is admin, bypassing max check");
    }
    SecureToken token = SecureTokenManager.getInstance().importToken(loginEvent.getWorldToken());
    boolean validToken = true;
    if (!token.getValid()) {
      Log.debug("token is not valid");
      validToken = false;
    }
    OID characterOid = (OID)token.getProperty("character_oid");
    if (Log.loggingDebug)
      Log.debug("PlayerOID: " + playerOid);
    if (Log.loggingDebug)
      Log.debug("CharacterOID: " + characterOid);
    if (!playerOid.equals(characterOid)) {
      Log.debug("playerOid does not match character_oid");
      validToken = false;
    }
    if (!token.getProperty("proxy_server").equals(Engine.getAgent().getName())) {
      Log.debug("proxy_server does not match engine agent name");
      validToken = false;
    }
    if (!validToken) {
      Log.error("processLogin: invalid proxy token");
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, this.tokenError, this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "invalid_token" }).increment();
      return false;
    }
    try {
      TargetMessage getPlayerLoginStatus = new TargetMessage(MSG_TYPE_GET_PLAYER_LOGIN_STATUS, playerOid);
      PlayerLoginStatus loginStatus = (PlayerLoginStatus)Engine.getAgent().sendRPCReturnObject((Message)getPlayerLoginStatus);
      if (this.proxyLoginCallback.duplicateLogin(loginStatus, con)) {
        if (loginStatus != null) {
          if (Log.loggingInfo)
            Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " name=" + loginStatus.name + " existingCon=" + loginStatus.clientCon + " existingProxy=" + loginStatus.proxyPluginName);
        } else if (Log.loggingInfo) {
          Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " loginStatus is null");
        }
        log.debug("processLogin: Send logout");
        Prometheus.registry().counter("player_logout", new String[] { "reason", "duplicate" }).increment();
        TargetMessage logoutPly = new TargetMessage(MSG_TYPE_LOGOUT_PLAYER, playerOid);
        Engine.getAgent().sendRPCReturnObject((Message)logoutPly);
        log.debug("processLogin: Send logout | ");
        AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Already connected", this.serverVersion);
        con.send(authorizedLoginResponseEvent.toBytes());
        Prometheus.registry().counter("player_login_result", new String[] { "status", "duplicate" }).increment();
        return false;
      }
    } catch (NoRecipientsException e) {
      if (Log.loggingDebug)
        log.debug("processLogin: OK! player is not logged " + e);
    }
    Player player = new Player(playerOid, con);
    player.setStatus(1);
    if (!this.playerManager.addPlayer(player)) {
      player = this.playerManager.getPlayer(playerOid);
      Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " existing=" + player.getConnection());
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Already connected", this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "duplicate_add" }).increment();
      return false;
    }
    con.setAssociation(player);
    player.setVersion(clientVersion);
    player.setCapabilities(clientCapabilities);
    String errorMessage = this.proxyLoginCallback.preLoad(player, con);
    if (errorMessage != null) {
      this.playerManager.removePlayer(playerOid);
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, errorMessage, this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "pre_load_error" }).increment();
      return false;
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: loading object: " + playerOid + ", con=" + con);
    if (!loadPlayerObject(player)) {
      Log.error("processLogin: could not load object " + playerOid);
      this.playerManager.removePlayer(playerOid);
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed", this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "not_loaded" }).increment();
      return false;
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: loaded player object: " + playerOid);
    errorMessage = this.proxyLoginCallback.postLoad(player, con);
    if (errorMessage != null) {
      this.playerManager.removePlayer(playerOid);
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, errorMessage, this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "error" }).increment();
      return false;
    }
    AuthorizedLoginResponseEvent loginResponse = new AuthorizedLoginResponseEvent(playerOid, true, "Login Succeeded", this.serverVersion + ", " + this.serverCapabilitiesSentToClient);
    con.send(loginResponse.toBytes());
    if (Log.loggingDebug)
      Log.debug("Login response sent for playerOid=" + playerOid + " the authorized login response message is : " + loginResponse.getMessage());
    this.playerManager.addStaticPerception(player, playerOid);
    boolean loginOK = processLoginHelper(con, player);
    if (Log.loggingDebug)
      log.debug("processLogin: loginOK?:" + loginOK + "  | player=" + player);
    if (!loginOK) {
      if (Log.loggingDebug)
        Log.debug("processLogin: loading object: " + playerOid + ", con=" + con + " login failed disconect player");
      con.setAssociation(null);
      if (this.perceptionFilter.removeTarget(playerOid)) {
        FilterUpdate filterUpdate = new FilterUpdate(1);
        filterUpdate.removeFieldValue(1, playerOid);
        Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
        this.responderFilter.removeTarget(playerOid);
        this.responderFilter2.removeTarget(playerOid);
        Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
        Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
      }
      this.playerManager.removeStaticPerception(player, playerOid);
      this.playerManager.removePlayer(playerOid);
      Prometheus.registry().counter("rdp_connection_closed", new String[] { "reason", "bad_login" }).increment();
      con.close();
    } else {
      this.proxyLoginCallback.postSpawn(player, con);
      this.playerManager.loginComplete(player, this.eventQQ);
      SubjectMessage loginSpawned = new SubjectMessage(MSG_TYPE_LOGIN_SPAWNED);
      loginSpawned.setSubject(playerOid);
      Engine.getAgent().sendBroadcast((Message)loginSpawned);
      processPlayerIgnoreList(player);
      OID accountID = (OID)EnginePlugin.getObjectProperty(playerOid, WorldManagerClient.NAMESPACE, "accountId");
      this.clientConnections.put(accountID, con);
      if (player.getStatus() == 3) {
        ConnectionResetMessage message = new ConnectionResetMessage(this, con, player);
        message.setEnqueueTime();
        this.messageQQ.insert(player, message);
      }
    }
    Prometheus.registry().counter("player_login_result", new String[] { "status", loginOK ? "ok" : "failed" }).increment();
    if (Log.loggingDebug) {
      log.debug("processLogin: loginOK?:" + loginOK + " || player=" + player);
      log.debug("processLogin: loginOK:" + loginOK + " end");
    }
    return loginOK;
  }
 
  protected boolean loadPlayerObject(Player player) {
    // Byte code:
    //   0: getstatic atavism/server/util/Log.loggingDebug : Z
    //   3: ifeq -> 32
    //   6: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   9: new java/lang/StringBuilder
    //   12: dup
    //   13: invokespecial <init> : ()V
    //   16: ldc_w 'loadPlayerObject player '
    //   19: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   22: aload_1
    //   23: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   26: invokevirtual toString : ()Ljava/lang/String;
    //   29: invokevirtual debug : (Ljava/lang/String;)V
    //   32: aconst_null
    //   33: astore_2
    //   34: aconst_null
    //   35: astore_3
    //   36: iconst_1
    //   37: istore #4
    //   39: aload_1
    //   40: invokevirtual getOid : ()Latavism/server/engine/OID;
    //   43: astore #5
    //   45: new java/util/ArrayList
    //   48: dup
    //   49: invokespecial <init> : ()V
    //   52: astore #6
    //   54: aload #5
    //   56: aload #6
    //   58: invokestatic loadSubObject : (Latavism/server/engine/OID;Ljava/util/Collection;)Latavism/server/engine/OID;
    //   61: astore #7
    //   63: getstatic atavism/server/util/Log.loggingDebug : Z
    //   66: ifeq -> 106
    //   69: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   72: new java/lang/StringBuilder
    //   75: dup
    //   76: invokespecial <init> : ()V
    //   79: ldc_w 'loadPlayerObject player '
    //   82: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   85: aload_1
    //   86: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   89: ldc_w ' oidResult='
    //   92: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   95: aload #7
    //   97: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   100: invokevirtual toString : ()Ljava/lang/String;
    //   103: invokevirtual debug : (Ljava/lang/String;)V
    //   106: aload #7
    //   108: ifnonnull -> 113
    //   111: iconst_0
    //   112: ireturn
    //   113: new atavism/server/math/Point
    //   116: dup
    //   117: invokespecial <init> : ()V
    //   120: astore #8
    //   122: invokestatic getDatabase : ()Latavism/server/engine/Database;
    //   125: aload #5
    //   127: getstatic atavism/server/plugins/WorldManagerClient.NAMESPACE : Latavism/server/engine/Namespace;
    //   130: aload #8
    //   132: invokevirtual getLocation : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Latavism/server/math/Point;)Latavism/server/engine/OID;
    //   135: astore #9
    //   137: getstatic atavism/server/util/Log.loggingDebug : Z
    //   140: ifeq -> 189
    //   143: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   146: new java/lang/StringBuilder
    //   149: dup
    //   150: invokespecial <init> : ()V
    //   153: ldc_w 'loadPlayerObject instanceOid '
    //   156: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   159: aload #9
    //   161: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   164: ldc_w ' instanceEntryAllowed:'
    //   167: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   170: aload_0
    //   171: aload #5
    //   173: aload #9
    //   175: aload #8
    //   177: invokespecial instanceEntryAllowed : (Latavism/server/engine/OID;Latavism/server/engine/OID;Latavism/server/math/Point;)Z
    //   180: invokevirtual append : (Z)Ljava/lang/StringBuilder;
    //   183: invokevirtual toString : ()Ljava/lang/String;
    //   186: invokevirtual debug : (Ljava/lang/String;)V
    //   189: getstatic atavism/server/util/Log.loggingDebug : Z
    //   192: ifeq -> 222
    //   195: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   198: new java/lang/StringBuilder
    //   201: dup
    //   202: invokespecial <init> : ()V
    //   205: ldc_w 'loadPlayerObject: trying to load player into instance: '
    //   208: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   211: aload #9
    //   213: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   216: invokevirtual toString : ()Ljava/lang/String;
    //   219: invokevirtual debug : (Ljava/lang/String;)V
    //   222: aload_0
    //   223: getfield aDB : Latavism/agis/database/AccountDatabase;
    //   226: aload #5
    //   228: invokevirtual GetGuildId : (Latavism/server/engine/OID;)I
    //   231: istore #10
    //   233: getstatic atavism/server/util/Log.loggingDebug : Z
    //   236: ifeq -> 266
    //   239: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   242: new java/lang/StringBuilder
    //   245: dup
    //   246: invokespecial <init> : ()V
    //   249: ldc_w 'loadPlayerObject: load player guildID: '
    //   252: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   255: iload #10
    //   257: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   260: invokevirtual toString : ()Ljava/lang/String;
    //   263: invokevirtual debug : (Ljava/lang/String;)V
    //   266: aconst_null
    //   267: astore #11
    //   269: aload_0
    //   270: aload #5
    //   272: aload #9
    //   274: aload #8
    //   276: invokespecial instanceEntryAllowed : (Latavism/server/engine/OID;Latavism/server/engine/OID;Latavism/server/math/Point;)Z
    //   279: ifeq -> 471
    //   282: aload #9
    //   284: ldc_w -262145
    //   287: invokestatic getInstanceInfo : (Latavism/server/engine/OID;I)Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   290: astore #12
    //   292: getstatic atavism/server/util/Log.loggingDebug : Z
    //   295: ifeq -> 387
    //   298: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   301: new java/lang/StringBuilder
    //   304: dup
    //   305: invokespecial <init> : ()V
    //   308: ldc_w 'loadPlayerObject InstanceInfo '
    //   311: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   314: aload #12
    //   316: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   319: ldc_w ' plyOid='
    //   322: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   325: aload #12
    //   327: getfield playerOid : Latavism/server/engine/OID;
    //   330: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   333: ldc_w ' tempId'
    //   336: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   339: aload #12
    //   341: getfield templateID : I
    //   344: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   347: ldc_w ' groupId'
    //   350: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   353: aload #12
    //   355: getfield groupOid : Latavism/server/engine/OID;
    //   358: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   361: ldc_w ' guildId'
    //   364: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   367: aload #12
    //   369: getfield guildId : I
    //   372: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   375: ldc_w ' start do '
    //   378: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   381: invokevirtual toString : ()Ljava/lang/String;
    //   384: invokevirtual debug : (Ljava/lang/String;)V
    //   387: aload #12
    //   389: getfield oid : Latavism/server/engine/OID;
    //   392: ifnull -> 471
    //   395: aload #12
    //   397: getfield populationLimit : I
    //   400: iconst_1
    //   401: if_icmplt -> 417
    //   404: aload #12
    //   406: getfield playerPopulation : I
    //   409: aload #12
    //   411: getfield populationLimit : I
    //   414: if_icmpge -> 471
    //   417: aload #5
    //   419: invokestatic loadObject : (Latavism/server/engine/OID;)Latavism/server/engine/OID;
    //   422: astore #11
    //   424: getstatic atavism/server/util/Log.loggingDebug : Z
    //   427: ifeq -> 471
    //   430: new java/lang/StringBuilder
    //   433: dup
    //   434: invokespecial <init> : ()V
    //   437: ldc_w 'loadPlayerObject: loading player into instance: '
    //   440: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   443: aload #12
    //   445: getfield oid : Latavism/server/engine/OID;
    //   448: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   451: ldc_w ' of ID: '
    //   454: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   457: aload #12
    //   459: getfield templateID : I
    //   462: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   465: invokevirtual toString : ()Ljava/lang/String;
    //   468: invokestatic debug : (Ljava/lang/String;)V
    //   471: aload_3
    //   472: ifnull -> 494
    //   475: aload_2
    //   476: invokevirtual getFallbackFlag : ()Z
    //   479: ifne -> 494
    //   482: aload #5
    //   484: getstatic atavism/server/engine/Namespace.OBJECT_MANAGER : Latavism/server/engine/Namespace;
    //   487: ldc 'instanceStack'
    //   489: aload_3
    //   490: invokestatic setObjectProperty : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Ljava/lang/String;Ljava/io/Serializable;)Ljava/io/Serializable;
    //   493: pop
    //   494: aload #11
    //   496: ifnull -> 559
    //   499: aload_2
    //   500: ifnull -> 1461
    //   503: aload #5
    //   505: getstatic atavism/server/engine/Namespace.OBJECT_MANAGER : Latavism/server/engine/Namespace;
    //   508: ldc 'currentInstanceName'
    //   510: aload_2
    //   511: invokevirtual getInstanceID : ()I
    //   514: invokestatic valueOf : (I)Ljava/lang/Integer;
    //   517: invokestatic setObjectProperty : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Ljava/lang/String;Ljava/io/Serializable;)Ljava/io/Serializable;
    //   520: pop
    //   521: getstatic atavism/server/util/Log.loggingDebug : Z
    //   524: ifeq -> 1461
    //   527: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   530: new java/lang/StringBuilder
    //   533: dup
    //   534: invokespecial <init> : ()V
    //   537: ldc_w 'INSTANCE: setting current instance prop: '
    //   540: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   543: aload_2
    //   544: invokevirtual getInstanceID : ()I
    //   547: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   550: invokevirtual toString : ()Ljava/lang/String;
    //   553: invokevirtual debug : (Ljava/lang/String;)V
    //   556: goto -> 1461
    //   559: iload #4
    //   561: ifeq -> 1092
    //   564: aload #5
    //   566: getstatic atavism/server/engine/Namespace.OBJECT_MANAGER : Latavism/server/engine/Namespace;
    //   569: ldc 'currentInstanceName'
    //   571: invokestatic getObjectProperty : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Ljava/lang/String;)Ljava/io/Serializable;
    //   574: checkcast java/lang/Integer
    //   577: astore #12
    //   579: getstatic atavism/server/util/Log.loggingDebug : Z
    //   582: ifeq -> 612
    //   585: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   588: new java/lang/StringBuilder
    //   591: dup
    //   592: invokespecial <init> : ()V
    //   595: ldc_w 'Failed initial load, retrying with current instanceID='
    //   598: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   601: aload #12
    //   603: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   606: invokevirtual toString : ()Ljava/lang/String;
    //   609: invokevirtual debug : (Ljava/lang/String;)V
    //   612: getstatic atavism/server/util/Log.loggingDebug : Z
    //   615: ifeq -> 667
    //   618: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   621: new java/lang/StringBuilder
    //   624: dup
    //   625: invokespecial <init> : ()V
    //   628: ldc_w ' loadPlayerObject instanceID='
    //   631: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   634: aload #12
    //   636: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   639: ldc_w '  playerOid='
    //   642: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   645: aload #5
    //   647: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   650: ldc_w ' guildID='
    //   653: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   656: iload #10
    //   658: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   661: invokevirtual toString : ()Ljava/lang/String;
    //   664: invokevirtual debug : (Ljava/lang/String;)V
    //   667: aload #12
    //   669: invokevirtual intValue : ()I
    //   672: ifle -> 1092
    //   675: aload_0
    //   676: getfield instanceEntryCallback : Latavism/server/objects/InstanceEntryCallback;
    //   679: aload_1
    //   680: aload #12
    //   682: invokevirtual intValue : ()I
    //   685: aload #5
    //   687: iload #10
    //   689: invokeinterface selectInstance : (Latavism/server/objects/Player;ILatavism/server/engine/OID;I)Latavism/server/engine/OID;
    //   694: astore #9
    //   696: getstatic atavism/server/util/Log.loggingDebug : Z
    //   699: ifeq -> 729
    //   702: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   705: new java/lang/StringBuilder
    //   708: dup
    //   709: invokespecial <init> : ()V
    //   712: ldc_w 'loadPlayerObject instanceOid:'
    //   715: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   718: aload #9
    //   720: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   723: invokevirtual toString : ()Ljava/lang/String;
    //   726: invokevirtual debug : (Ljava/lang/String;)V
    //   729: aload #9
    //   731: ifnull -> 1092
    //   734: aload #9
    //   736: ldc_w -262145
    //   739: iconst_0
    //   740: invokestatic getInstanceInfo : (Latavism/server/engine/OID;IZ)Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   743: astore #13
    //   745: getstatic atavism/server/util/Log.loggingDebug : Z
    //   748: ifeq -> 834
    //   751: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   754: new java/lang/StringBuilder
    //   757: dup
    //   758: invokespecial <init> : ()V
    //   761: ldc_w ' loadPlayerObject InstanceInfo '
    //   764: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   767: aload #13
    //   769: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   772: ldc_w ' plyOid='
    //   775: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   778: aload #13
    //   780: getfield playerOid : Latavism/server/engine/OID;
    //   783: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   786: ldc_w ' tempId='
    //   789: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   792: aload #13
    //   794: getfield templateID : I
    //   797: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   800: ldc_w ' groupId='
    //   803: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   806: aload #13
    //   808: getfield groupOid : Latavism/server/engine/OID;
    //   811: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   814: ldc_w ' guildId='
    //   817: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   820: aload #13
    //   822: getfield guildId : I
    //   825: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   828: invokevirtual toString : ()Ljava/lang/String;
    //   831: invokevirtual debug : (Ljava/lang/String;)V
    //   834: aload #13
    //   836: getfield oid : Latavism/server/engine/OID;
    //   839: ifnull -> 1092
    //   842: aload #13
    //   844: getfield populationLimit : I
    //   847: ifle -> 1015
    //   850: aload #13
    //   852: getfield playerPopulation : I
    //   855: aload #13
    //   857: getfield populationLimit : I
    //   860: if_icmplt -> 1015
    //   863: getstatic atavism/server/util/Log.loggingDebug : Z
    //   866: ifeq -> 910
    //   869: new java/lang/StringBuilder
    //   872: dup
    //   873: invokespecial <init> : ()V
    //   876: ldc_w 'POP: got population: '
    //   879: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   882: aload #13
    //   884: getfield playerPopulation : I
    //   887: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   890: ldc_w ' and limit: '
    //   893: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   896: aload #13
    //   898: getfield populationLimit : I
    //   901: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   904: invokevirtual toString : ()Ljava/lang/String;
    //   907: invokestatic debug : (Ljava/lang/String;)V
    //   910: aload #13
    //   912: getfield templateID : I
    //   915: aload #13
    //   917: invokestatic handleFullInstance : (ILatavism/server/plugins/InstanceClient$InstanceInfo;)Latavism/server/engine/OID;
    //   920: astore #9
    //   922: aload #9
    //   924: ldc_w -262145
    //   927: invokestatic getInstanceInfo : (Latavism/server/engine/OID;I)Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   930: astore #13
    //   932: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   935: new java/lang/StringBuilder
    //   938: dup
    //   939: invokespecial <init> : ()V
    //   942: ldc_w ' loadPlayerObject 2 InstanceInfo '
    //   945: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   948: aload #13
    //   950: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   953: ldc_w ' plyOid'
    //   956: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   959: aload #13
    //   961: getfield playerOid : Latavism/server/engine/OID;
    //   964: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   967: ldc_w ' tempId='
    //   970: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   973: aload #13
    //   975: getfield templateID : I
    //   978: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   981: ldc_w ' groupId='
    //   984: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   987: aload #13
    //   989: getfield groupOid : Latavism/server/engine/OID;
    //   992: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   995: ldc_w ' guildId='
    //   998: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1001: aload #13
    //   1003: getfield guildId : I
    //   1006: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   1009: invokevirtual toString : ()Ljava/lang/String;
    //   1012: invokevirtual debug : (Ljava/lang/String;)V
    //   1015: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1018: ifeq -> 1062
    //   1021: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1024: new java/lang/StringBuilder
    //   1027: dup
    //   1028: invokespecial <init> : ()V
    //   1031: ldc_w 'Failed initial load, retrying with instanceOid='
    //   1034: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1037: aload #9
    //   1039: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1042: ldc_w ' and instanceName: '
    //   1045: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1048: aload #13
    //   1050: getfield name : Ljava/lang/String;
    //   1053: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1056: invokevirtual toString : ()Ljava/lang/String;
    //   1059: invokevirtual debug : (Ljava/lang/String;)V
    //   1062: new atavism/server/engine/BasicWorldNode
    //   1065: dup
    //   1066: invokespecial <init> : ()V
    //   1069: astore #14
    //   1071: aload #14
    //   1073: aload #9
    //   1075: invokevirtual setInstanceOid : (Latavism/server/engine/OID;)V
    //   1078: aload #5
    //   1080: aload #14
    //   1082: invokestatic fixWorldNode : (Latavism/server/engine/OID;Latavism/server/engine/BasicWorldNode;)Z
    //   1085: pop
    //   1086: iconst_0
    //   1087: istore #4
    //   1089: goto -> 266
    //   1092: aload_2
    //   1093: ifnull -> 1167
    //   1096: aload_2
    //   1097: invokevirtual getFallbackFlag : ()Z
    //   1100: ifeq -> 1167
    //   1103: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1106: ifeq -> 1165
    //   1109: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1112: new java/lang/StringBuilder
    //   1115: dup
    //   1116: invokespecial <init> : ()V
    //   1119: ldc_w 'loadPlayerObject instanceOid '
    //   1122: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1125: aload #9
    //   1127: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1130: ldc_w ' restorePoint:'
    //   1133: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1136: aload_2
    //   1137: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1140: ldc_w ' restorePoint.getFallbackFlag():'
    //   1143: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1146: aload_2
    //   1147: invokevirtual getFallbackFlag : ()Z
    //   1150: invokevirtual append : (Z)Ljava/lang/StringBuilder;
    //   1153: ldc_w ' return false'
    //   1156: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1159: invokevirtual toString : ()Ljava/lang/String;
    //   1162: invokevirtual debug : (Ljava/lang/String;)V
    //   1165: iconst_0
    //   1166: ireturn
    //   1167: aload #5
    //   1169: getstatic atavism/server/engine/Namespace.OBJECT_MANAGER : Latavism/server/engine/Namespace;
    //   1172: ldc 'instanceStack'
    //   1174: invokestatic getObjectProperty : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Ljava/lang/String;)Ljava/io/Serializable;
    //   1177: checkcast java/util/LinkedList
    //   1180: astore_3
    //   1181: aload_3
    //   1182: ifnull -> 1192
    //   1185: aload_3
    //   1186: invokevirtual size : ()I
    //   1189: ifne -> 1223
    //   1192: new java/lang/StringBuilder
    //   1195: dup
    //   1196: invokespecial <init> : ()V
    //   1199: ldc_w 'Failed finding matching instance, and restore stack is null or empty?'
    //   1202: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1205: aload_3
    //   1206: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1209: ldc_w ' return false'
    //   1212: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1215: invokevirtual toString : ()Ljava/lang/String;
    //   1218: invokestatic error : (Ljava/lang/String;)V
    //   1221: iconst_0
    //   1222: ireturn
    //   1223: aload_3
    //   1224: invokevirtual size : ()I
    //   1227: istore #12
    //   1229: aload_3
    //   1230: iload #12
    //   1232: iconst_1
    //   1233: isub
    //   1234: invokevirtual get : (I)Ljava/lang/Object;
    //   1237: checkcast atavism/server/objects/InstanceRestorePoint
    //   1240: astore_2
    //   1241: aload_2
    //   1242: invokevirtual getInstanceOid : ()Latavism/server/engine/OID;
    //   1245: astore #9
    //   1247: aload_2
    //   1248: invokevirtual getInstanceID : ()I
    //   1251: ifle -> 1313
    //   1254: aload_0
    //   1255: getfield instanceEntryCallback : Latavism/server/objects/InstanceEntryCallback;
    //   1258: aload_1
    //   1259: aload_2
    //   1260: invokevirtual getInstanceID : ()I
    //   1263: invokeinterface selectInstance : (Latavism/server/objects/Player;I)Latavism/server/engine/OID;
    //   1268: astore #9
    //   1270: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1273: ifeq -> 1313
    //   1276: new java/lang/StringBuilder
    //   1279: dup
    //   1280: invokespecial <init> : ()V
    //   1283: ldc_w 'Failed finding matching instance, retrying with restore point instanceID='
    //   1286: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1289: aload_2
    //   1290: invokevirtual getInstanceID : ()I
    //   1293: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   1296: ldc_w ' result: '
    //   1299: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1302: aload #9
    //   1304: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1307: invokevirtual toString : ()Ljava/lang/String;
    //   1310: invokestatic debug : (Ljava/lang/String;)V
    //   1313: aload #9
    //   1315: ifnull -> 1439
    //   1318: new atavism/server/engine/BasicWorldNode
    //   1321: dup
    //   1322: invokespecial <init> : ()V
    //   1325: astore #13
    //   1327: aload #13
    //   1329: aload #9
    //   1331: invokevirtual setInstanceOid : (Latavism/server/engine/OID;)V
    //   1334: aload #13
    //   1336: aload_2
    //   1337: invokevirtual getLoc : ()Latavism/server/math/Point;
    //   1340: invokevirtual setLoc : (Latavism/server/math/Point;)V
    //   1343: aload #13
    //   1345: aload_2
    //   1346: invokevirtual getOrientation : ()Latavism/server/math/Quaternion;
    //   1349: invokevirtual setOrientation : (Latavism/server/math/Quaternion;)V
    //   1352: aload #13
    //   1354: new atavism/server/math/AOVector
    //   1357: dup
    //   1358: fconst_0
    //   1359: fconst_0
    //   1360: fconst_0
    //   1361: invokespecial <init> : (FFF)V
    //   1364: invokevirtual setDir : (Latavism/server/math/AOVector;)V
    //   1367: aload #5
    //   1369: aload #13
    //   1371: invokestatic fixWorldNode : (Latavism/server/engine/OID;Latavism/server/engine/BasicWorldNode;)Z
    //   1374: istore #14
    //   1376: iload #14
    //   1378: ifne -> 1433
    //   1381: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1384: ifeq -> 1431
    //   1387: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1390: new java/lang/StringBuilder
    //   1393: dup
    //   1394: invokespecial <init> : ()V
    //   1397: ldc_w 'loadPlayerObject instanceOid '
    //   1400: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1403: aload #9
    //   1405: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1408: ldc_w ' rc:'
    //   1411: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1414: iload #14
    //   1416: invokevirtual append : (Z)Ljava/lang/StringBuilder;
    //   1419: ldc_w ' return false'
    //   1422: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1425: invokevirtual toString : ()Ljava/lang/String;
    //   1428: invokevirtual debug : (Ljava/lang/String;)V
    //   1431: iconst_0
    //   1432: ireturn
    //   1433: aload_2
    //   1434: invokevirtual getLoc : ()Latavism/server/math/Point;
    //   1437: astore #8
    //   1439: iconst_0
    //   1440: istore #4
    //   1442: aload_2
    //   1443: invokevirtual getFallbackFlag : ()Z
    //   1446: ifne -> 1458
    //   1449: aload_3
    //   1450: iload #12
    //   1452: iconst_1
    //   1453: isub
    //   1454: invokevirtual remove : (I)Ljava/lang/Object;
    //   1457: pop
    //   1458: goto -> 266
    //   1461: goto -> 1521
    //   1464: astore #11
    //   1466: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1469: new java/lang/StringBuilder
    //   1472: dup
    //   1473: invokespecial <init> : ()V
    //   1476: ldc_w 'loadPlayerObject instanceOid '
    //   1479: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1482: aload #9
    //   1484: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1487: ldc_w ' Exception: '
    //   1490: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1493: aload #11
    //   1495: invokevirtual getMessage : ()Ljava/lang/String;
    //   1498: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1501: ldc_w ' '
    //   1504: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1507: aload #11
    //   1509: invokevirtual getLocalizedMessage : ()Ljava/lang/String;
    //   1512: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1515: invokevirtual toString : ()Ljava/lang/String;
    //   1518: invokevirtual error : (Ljava/lang/String;)V
    //   1521: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1524: ifeq -> 1560
    //   1527: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1530: new java/lang/StringBuilder
    //   1533: dup
    //   1534: invokespecial <init> : ()V
    //   1537: ldc_w 'loadPlayerObject instanceOid '
    //   1540: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1543: aload #9
    //   1545: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1548: ldc_w ' END return true'
    //   1551: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1554: invokevirtual toString : ()Ljava/lang/String;
    //   1557: invokevirtual debug : (Ljava/lang/String;)V
    //   1560: iconst_1
    //   1561: ireturn
    // Line number table:
    //   Java source line number -> byte code offset
    //   #1848    -> 0
    //   #1849    -> 6
    //   #1850    -> 32
    //   #1851    -> 34
    //   #1852    -> 36
    //   #1853    -> 39
    //   #1856    -> 45
    //   #1857    -> 54
    //   #1858    -> 63
    //   #1859    -> 69
    //   #1860    -> 106
    //   #1861    -> 111
    //   #1864    -> 113
    //   #1865    -> 122
    //   #1866    -> 137
    //   #1867    -> 143
    //   #1869    -> 189
    //   #1870    -> 195
    //   #1872    -> 222
    //   #1873    -> 233
    //   #1874    -> 239
    //   #1877    -> 266
    //   #1878    -> 269
    //   #1879    -> 282
    //   #1880    -> 292
    //   #1881    -> 298
    //   #1884    -> 387
    //   #1887    -> 417
    //   #1888    -> 424
    //   #1889    -> 430
    //   #1894    -> 471
    //   #1895    -> 482
    //   #1898    -> 494
    //   #1899    -> 499
    //   #1900    -> 503
    //   #1901    -> 521
    //   #1902    -> 527
    //   #1909    -> 559
    //   #1911    -> 564
    //   #1912    -> 579
    //   #1913    -> 585
    //   #1914    -> 612
    //   #1915    -> 618
    //   #1917    -> 667
    //   #1928    -> 675
    //   #1929    -> 696
    //   #1930    -> 702
    //   #1931    -> 729
    //   #1933    -> 734
    //   #1934    -> 745
    //   #1935    -> 751
    //   #1936    -> 834
    //   #1937    -> 842
    //   #1938    -> 863
    //   #1939    -> 869
    //   #1940    -> 910
    //   #1941    -> 922
    //   #1942    -> 932
    //   #1944    -> 1015
    //   #1945    -> 1021
    //   #1946    -> 1062
    //   #1947    -> 1071
    //   #1948    -> 1078
    //   #1949    -> 1086
    //   #1950    -> 1089
    //   #1957    -> 1092
    //   #1958    -> 1103
    //   #1959    -> 1109
    //   #1961    -> 1165
    //   #1965    -> 1167
    //   #1967    -> 1181
    //   #1968    -> 1192
    //   #1969    -> 1221
    //   #1973    -> 1223
    //   #1974    -> 1229
    //   #1976    -> 1241
    //   #1978    -> 1247
    //   #1979    -> 1254
    //   #1980    -> 1270
    //   #1983    -> 1313
    //   #1984    -> 1318
    //   #1985    -> 1327
    //   #1987    -> 1334
    //   #1988    -> 1343
    //   #1989    -> 1352
    //   #1991    -> 1367
    //   #1993    -> 1376
    //   #1994    -> 1381
    //   #1995    -> 1387
    //   #1997    -> 1431
    //   #1999    -> 1433
    //   #2001    -> 1439
    //   #2003    -> 1442
    //   #2004    -> 1449
    //   #2007    -> 1458
    //   #2011    -> 1461
    //   #2008    -> 1464
    //   #2009    -> 1466
    //   #2012    -> 1521
    //   #2013    -> 1527
    //   #2015    -> 1560
    // Local variable table:
    //   start    length    slot    name    descriptor
    //   292    179    12    instanceInfo    Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   1071    21    14    wnode    Latavism/server/engine/BasicWorldNode;
    //   745    347    13    instanceInfo    Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   579    513    12    instanceID    Ljava/lang/Integer;
    //   1327    112    13    wnode    Latavism/server/engine/BasicWorldNode;
    //   1376    63    14    rc    Z
    //   269    1189    11    result    Latavism/server/engine/OID;
    //   1229    229    12    size    I
    //   1466    55    11    e    Ljava/lang/Exception;
    //   0    1562    0    this    Latavism/server/plugins/ProxyPlugin;
    //   0    1562    1    player    Latavism/server/objects/Player;
    //   34    1528    2    restorePoint    Latavism/server/objects/InstanceRestorePoint;
    //   36    1526    3    restoreStack    Ljava/util/LinkedList;
    //   39    1523    4    first    Z
    //   45    1517    5    playerOid    Latavism/server/engine/OID;
    //   54    1508    6    namespaces    Ljava/util/List;
    //   63    1499    7    oidResult    Latavism/server/engine/OID;
    //   122    1440    8    location    Latavism/server/math/Point;
    //   137    1425    9    instanceOid    Latavism/server/engine/OID;
    //   233    1329    10    guildID    I
    // Local variable type table:
    //   start    length    slot    name    signature
    //   54    1508    6    namespaces    Ljava/util/List<Latavism/server/engine/Namespace;>;
    // Exception table:
    //   from    to    target    type
    //   266    1166    1464    java/lang/Exception
    //   1167    1222    1464    java/lang/Exception
    //   1223    1432    1464    java/lang/Exception
    //   1433    1461    1464    java/lang/Exception
  }
 
  protected boolean processLoginHelper(ClientConnection con, Player player) {
    OID playerOid = player.getOid();
    WorldManagerClient.ObjectInfo objInfo = WorldManagerClient.getObjectInfo(playerOid);
    if (objInfo == null) {
      Log.error("processLogin: Could not get player ObjectInfo oid=" + playerOid);
      return false;
    }
    if (Log.loggingDebug)
      log.debug("processLoginHelper objInfo " + objInfo.instanceOid);
    if (World.FollowsTerrainOverride != null) {
      Log.debug("using follows terrain override");
      objInfo.followsTerrain = World.FollowsTerrainOverride.booleanValue();
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: got object info: " + objInfo);
    player.setName(objInfo.name);
    InstanceClient.InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(objInfo.instanceOid, -262145);
    if (Log.loggingDebug)
      log.debug("InstanceInfo " + instanceInfo + " " + instanceInfo.playerOid + " " + instanceInfo.templateID + " " + instanceInfo.groupOid + " " + instanceInfo.guildId);
    if (instanceInfo == null) {
      Log.error("processLogin: unknown instanceOid=" + objInfo.instanceOid);
      return false;
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: sending template (scene) name: " + instanceInfo.templateName);
    WorldFileEvent worldFileEvent = new WorldFileEvent(instanceInfo.templateName);
    con.send(worldFileEvent.toBytes());
    player.sceneLoading(true);
    Log.debug("INFO: process login helper");
    con.send(objInfo.toBuffer(playerOid));
    DisplayContext dc = WorldManagerClient.getDisplayContext(playerOid);
    ModelInfoEvent modelInfoEvent = new ModelInfoEvent(playerOid);
    modelInfoEvent.setDisplayContext(dc);
    if (Log.loggingDebug)
      Log.debug("processLogin: got dc: " + dc);
    con.send(modelInfoEvent.toBytes());
    Map<String, DisplayContext> childMap = dc.getChildDCMap();
    if (childMap != null && !childMap.isEmpty()) {
      for (String slot : childMap.keySet()) {
        DisplayContext attachDC = childMap.get(slot);
        if (attachDC == null)
          throw new AORuntimeException("attach DC is null for obj: " + playerOid);
        OID attacheeOID = attachDC.getObjRef();
        if (attacheeOID == null)
          throw new AORuntimeException("attachee oid is null for obj: " + playerOid);
        if (Log.loggingDebug)
          Log.debug("processLogin: sending attach message to " + playerOid + " attaching to obj " + playerOid + ", object being attached=" + attacheeOID + " to slot " + slot + ", attachmentDC=" + attachDC);
        AttachEvent event = new AttachEvent(playerOid, attacheeOID, slot, attachDC);
        con.send(event.toBytes());
      }
      Log.debug("processLogin: done with processing attachments");
    }
    if (this.perceptionFilter.addTarget(playerOid)) {
      FilterUpdate filterUpdate = new FilterUpdate(1);
      filterUpdate.addFieldValue(1, playerOid);
      Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
      this.responderFilter.addTarget(playerOid);
      this.responderFilter2.addTarget(playerOid);
      Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
      Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
    }
    LoginMessage loginMessage = new LoginMessage(playerOid, objInfo.name);
    loginMessage.setInstanceOid(objInfo.instanceOid);
    loginMessage.setProxy(getName());
    AsyncRPCCallback asyncRPCCallback = new AsyncRPCCallback(player, "processLogin: got LoginMessage response");
    int expectedResponses = Engine.getAgent().sendBroadcastRPC((Message)loginMessage, (ResponseCallback)asyncRPCCallback);
    asyncRPCCallback.waitForResponses(expectedResponses);
    WorldManagerClient.updateObject(playerOid, playerOid);
    WorldManagerClient.TargetedExtensionMessage spawnBegin = new WorldManagerClient.TargetedExtensionMessage(playerOid, playerOid);
    spawnBegin.setExtensionType("ao.SCENE_BEGIN");
    spawnBegin.setProperty("action", "login");
    spawnBegin.setProperty("name", instanceInfo.name);
    spawnBegin.setProperty("templateName", instanceInfo.templateName);
    WorldManagerClient.TargetedExtensionMessage spawnEnd = new WorldManagerClient.TargetedExtensionMessage(playerOid, playerOid);
    spawnEnd.setExtensionType("ao.SCENE_END");
    spawnEnd.setProperty("action", "login");
    spawnEnd.setProperty("name", instanceInfo.name);
    spawnEnd.setProperty("templateName", instanceInfo.templateName);
    Integer perceptionCount = WorldManagerClient.spawn(playerOid, (Message)spawnBegin, (Message)spawnEnd);
    if (perceptionCount.intValue() < 0) {
      Log.error("processLogin: spawn failed error=" + perceptionCount + " playerOid=" + playerOid);
      if (perceptionCount.intValue() == -2)
        return false;
      return false;
    }
    if (perceptionCount.intValue() == 0 && player.supportsLoadingState()) {
      player.setLoadingState(1);
      con.send((new LoadingStateEvent(false)).toBytes());
    }
    if (Log.loggingDebug) {
      Log.debug("processLogin: During login, perceptionCount is " + perceptionCount);
      Log.debug("processLogin: spawned player, master playerOid=" + playerOid);
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: sending over instance information for player " + playerOid + ", instance=" + instanceInfo.name + ", instanceOid=" + instanceInfo.oid);
    updateInstancePerception(player.getOid(), null, instanceInfo.oid, instanceInfo.name);
    return true;
  }
 
  public ProxyLoginCallback getProxyLoginCallback() {
    return this.proxyLoginCallback;
  }
 
  public void setProxyLoginCallback(ProxyLoginCallback callback) {
    this.proxyLoginCallback = callback;
  }
 
  private boolean instanceEntryAllowed(OID playerOid, OID instanceOid, Point location) {
    if (instanceOid == null)
      return false;
    return this.instanceEntryCallback.instanceEntryAllowed(playerOid, instanceOid, location);
  }
 
  public InstanceEntryCallback getInstanceEntryCallback() {
    return this.instanceEntryCallback;
  }
 
  public void setInstanceEntryCallback(InstanceEntryCallback callback) {
    this.instanceEntryCallback = callback;
  }
 
  public void processRequestQuestInfo(ClientConnection con, RequestQuestInfo event) {
    OID npcOid = event.getQuestNpcOid();
    Player player = verifyPlayer("processRequestQuestInfo", (Event)event, con);
    if (Log.loggingDebug)
      Log.debug("processRequestQuestInfo: player=" + player + ", npc=" + npcOid);
    QuestClient.requestQuestInfo(npcOid, player.getOid());
  }
 
  public void processQuestResponse(ClientConnection con, QuestResponse event) {
    Player player = verifyPlayer("processQuestResponse", (Event)event, con);
    boolean acceptStatus = event.getResponse();
    OID npcOid = event.getQuestNpcOid();
    OID questOid = event.getQuestId();
    if (Log.loggingDebug)
      Log.debug("processQuestResponse: player=" + player + ", npcOid=" + npcOid + ", acceptStatus=" + acceptStatus);
    QuestClient.QuestResponseMessage msg = new QuestClient.QuestResponseMessage(npcOid, player.getOid(), questOid, acceptStatus);
    Engine.getAgent().sendBroadcast((Message)msg);
  }
 
  public void processReqConcludeQuest(ClientConnection con, ConcludeQuest event) {
    Player player = verifyPlayer("processReqConcludeQuest", (Event)event, con);
    OID mobOid = event.getQuestNpcOid();
    if (Log.loggingDebug)
      Log.debug("processReqConclude: player=" + player + ", mobOid=" + mobOid);
    QuestClient.requestConclude(mobOid, player.getOid());
  }
 
  public void connectionReset(ClientConnection con) {
    Player player = (Player)con.getAssociation();
    if (player == null) {
      Log.info("ProxyPlugin: DISCONNECT remote=" + con);
      return;
    }
    if (Log.loggingInfo) {
      Log.info("ProxyPlugin: DISCONNECT remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName() + " player=" + player);
      Log.info("ProxyPlugin: DISCONNECT remote=" + con + " player=" + player);
    }
    this.playerManager.logout(player);
    ConnectionResetMessage message = new ConnectionResetMessage(this, con, player);
    message.setEnqueueTime();
    this.messageQQ.insert(player, message);
  }
 
  protected void processConnectionResetInternal(ConnectionResetMessage message) {
    long startTime = System.currentTimeMillis();
    ClientConnection con = message.getConnection();
    Player player = message.getPlayer();
    OID playerOid = player.getOid();
    if (Log.loggingInfo)
      Log.info("ProxyPlugin: LOGOUT_BEGIN remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName());
    if (player.getStatus() != 3) {
      log.error("processConnectionReset: player status is " + Player.statusToString(player.getStatus()) + " should be " + Player.statusToString(3));
      player.setStatus(3);
    }
    try {
      try {
        if (!WorldManagerClient.despawn(playerOid))
          log.warn("processConnectionReset: despawn player failed for " + playerOid);
      } catch (Exception e) {
        log.warn("processConnectionReset: despawn player failed for " + playerOid + " " + e);
      }
      if (Log.loggingDebug)
        Log.debug("processConnectionResetInternal Removing perceptionFilter for palyer: " + playerOid);
      if (this.perceptionFilter.removeTarget(playerOid)) {
        FilterUpdate filterUpdate = new FilterUpdate(1);
        filterUpdate.removeFieldValue(1, playerOid);
        if (Log.loggingDebug)
          Log.debug("processConnectionResetInternal Removing perceptionFilter applyFilterUpdate for palyer: " + playerOid);
        Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
        if (Log.loggingDebug)
          Log.debug("processConnectionResetInternal Removing responderFilter for palyer: " + playerOid);
        this.responderFilter.removeTarget(playerOid);
        this.responderFilter2.removeTarget(playerOid);
        if (Log.loggingDebug)
          Log.debug("processConnectionResetInternal Removing perceptionFilter applyFilterUpdate for palyer: " + playerOid);
        Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
        Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
      }
      LogoutMessage logoutMessage = new LogoutMessage(playerOid, player.getName());
      if (Log.loggingDebug)
        Log.debug("processConnectionResetInternal: Send LogoutMessage for player: " + playerOid + "  and wait for response");
      AsyncRPCCallback asyncRPCCallback = new AsyncRPCCallback(player, "processLogout: got LogoutMessage response");
      int expectedResponses = Engine.getAgent().sendBroadcastRPC((Message)logoutMessage, (ResponseCallback)asyncRPCCallback);
      if (Log.loggingDebug)
        Log.debug("processConnectionResetInternal: Send LogoutMessage for player: " + playerOid + "  and wait for response expectedResponses=" + expectedResponses);
      asyncRPCCallback.waitForResponses(expectedResponses);
      OID accountID = this.aDB.getAccountForCharacter(playerOid);
      if (Log.loggingDebug)
        Log.debug("Removing connection from client connection map for account: " + accountID);
      if (this.clientConnections.containsKey(accountID) && ((ClientConnection)this.clientConnections.get(accountID)).isOpen()) {
        Prometheus.registry().counter("rdp_connection_closed", new String[] { "reason", "internal_reset" }).increment();
        ((ClientConnection)this.clientConnections.get(accountID)).close();
      }
      this.clientConnections.remove(accountID);
      if (!ObjectManagerClient.unloadObject(playerOid).booleanValue())
        log.warn("processConnectionReset: unloadObject failed oid=" + playerOid);
    } catch (NoRecipientsException nre) {
      log.exception("ProxyPlugin.processConnectionResetInternal(): NoRecipientsException ", (Exception)nre);
    } catch (RPCTimeoutException nre) {
      log.exception("ProxyPlugin.processConnectionResetInternal(): RPCTimeoutException ", (Exception)nre);
    } catch (Exception nre) {
      log.exception("ProxyPlugin.processConnectionResetInternal(): Exception ", nre);
    }
    this.messageQQ.removeKey(player);
    this.eventQQ.removeKey(player);
    con.closeAggregator();
    this.playerManager.removeStaticPerception(player, playerOid);
    this.playerManager.removePlayer(playerOid);
    if (Log.loggingInfo)
      Log.info("ProxyPlugin: LOGOUT_END remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName() + " in-queue=" + (startTime - message.getEnqueueTime()) + " processing=" + (System.currentTimeMillis() - startTime) + " nPlayers=" + this.playerManager.getPlayerCount());
    synchronized (player) {
      player.clearConnection();
      player.notifyAll();
    }
  }
 
  protected void processPlayerHa(ClientConnection con, PlayerHaEvent event) {
    if (Log.loggingDebug)
      Log.debug("processPlayerHa: got dir loc orient event: " + event);
    Player player = verifyPlayer("processPlayerHa", (Event)event, con);
    long stime = System.currentTimeMillis();
    long ctime = event.getTime();
    long lctime = 0L;
    long lstime = 0L;
    try {
      lctime = ((Long)this.playerLastClientTime.get(player.getOid())).longValue();
    } catch (Exception exception) {}
    try {
      lstime = ((Long)this.playerLastServerTime.get(player.getOid())).longValue();
    } catch (Exception exception) {}
    this.playerLastClientTime.put(player.getOid(), Long.valueOf(event.getTime()));
    this.playerLastServerTime.put(player.getOid(), Long.valueOf(stime));
    if (lctime > 0L && lstime > 0L && stime - lstime < SpeedhackMinDiff) {
      log.error("SPEEDHACK detected plyOid=" + player.getOid() + " Ct=" + ctime + " LCT=" + lctime + " ST=" + stime + " LST=" + lstime + " dst=" + (stime - lstime) + " dct=" + (ctime - lctime));
      long count = 0L;
      try {
        count = ((Long)this.playerSpeedHackCount.get(player.getOid())).longValue();
      } catch (Exception exception) {}
      count++;
      this.playerSpeedHackCount.put(player.getOid(), Long.valueOf(count));
      long fdtime = 0L;
      try {
        fdtime = ((Long)this.playerFirstSpeedHackTime.get(player.getOid())).longValue();
      } catch (Exception exception) {}
      if (fdtime == 0L) {
        fdtime = stime;
        this.playerFirstSpeedHackTime.put(player.getOid(), Long.valueOf(fdtime));
      }
      if (SpeedhackChatMsg.length() > 1) {
        ChatClient.TargetedComMessage comMsg = new ChatClient.TargetedComMessage();
        comMsg.setString(SpeedhackChatMsg);
        comMsg.setChannel(0);
        comMsg.setChatterName("Admin");
        comMsg.setTarget(player.getOid());
        Engine.getAgent().sendBroadcast((Message)comMsg);
      }
      HashMap<String, Serializable> logData = new HashMap<>();
      logData.put("serverDeltaTime", Long.valueOf(stime - lstime));
      logData.put("clientDeltaTime", Long.valueOf(ctime - lctime));
      logData.put("firstDetection", Long.valueOf(fdtime));
      logData.put("count", Long.valueOf(count));
      DataLoggerClient.logData("SPEEDHACK", player.getOid(), null, null, logData);
      if (count > SpeedhackCountToDisconect) {
        Prometheus.registry().counter("rdp_connection_closed", new String[] { "reason", "speed_hack" }).increment();
        con.close();
        this.playerLastClientTime.remove(player.getOid());
        this.playerLastServerTime.remove(player.getOid());
        this.playerFirstSpeedHackTime.remove(player.getOid());
        this.playerSpeedHackCount.remove(player.getOid());
      }
    }
  }
 
  protected void processDirLocOrient(ClientConnection con, DirLocOrientEvent event) {
    if (Log.loggingDebug)
      Log.debug("processDirLocOrient: got dir loc orient event: " + event);
    Player player = verifyPlayer("processDirLoc", (Event)event, con);
    BasicWorldNode wnode = new BasicWorldNode();
    wnode.setDir(event.getDir());
    wnode.setLoc(event.getLoc());
    wnode.setOrientation(event.getQuaternion());
    wnode.time = event.getTime();
    wnode.mid = event.getId();
    wnode.cid = event.getUId();
    WorldManagerClient.updateWorldNode(player.getOid(), wnode);
  }
 
  protected void processCom(ClientConnection con, ComEvent event) {
    Player player = verifyPlayer("processCom", (Event)event, con);
    if (Log.loggingInfo)
      Log.info("ProxyPlugin: CHAT_SENT player=" + player + " channel=" + event.getChannelId() + " msg=[" + event.getMessage() + "]");
    log.debug("processCom: CHAT_SENT");
    if (this.aDB.isOnBlackList(player.getOid(), event.getObjectOid()))
      return;
    incrementChatCount();
    ChatClient.sendChatMsg(player.getOid(), player.getName(), event.getChannelId(), event.getMessage());
  }
 
  protected void processCommand(ClientConnection con, CommandEvent event) {
    RegisteredCommand command;
    Player player = verifyPlayer("processCommand", (Event)event, con);
    String cmd = event.getCommand().split(" ")[0];
    if (Log.loggingDebug)
      log.debug("processCommand: cmd=" + cmd + ", fullCmd=" + event.getCommand());
    this.commandMapLock.lock();
    try {
      command = this.commandMap.get(cmd);
    } finally {
      this.commandMapLock.unlock();
    }
    if (command == null) {
      Log.warn("processCommand: no parser for command: " + event.getCommand());
      command = this.commandMap.get("/unknowncmd");
      if (command != null) {
        Engine.setCurrentPlugin(this);
        command.parser.parse(event);
        Engine.setCurrentPlugin(null);
      }
      return;
    }
    Engine.setCurrentPlugin(this);
    if (command.access.allowed(event, this)) {
      command.parser.parse(event);
    } else {
      Log.warn("Player " + player + " not allowed to run command '" + event.getCommand() + "'");
    }
    Engine.setCurrentPlugin(null);
  }
 
  protected void processAutoAttack(ClientConnection con, AutoAttackEvent event) {
    CombatClient.autoAttack(event.getAttackerOid(), event.getTargetOid(), event.getAttackStatus());
  }
 
  protected void processActivateItem(ClientConnection con, ActivateItemEvent event) {
    InventoryClient.activateObject(event.getItemOid(), event.getObjectOid(), event.getTargetOid());
  }
 
  protected void processAbilityStatusEvent(ClientConnection con, AbilityStatusEvent event) {
    Player player = (Player)con.getAssociation();
    AbilityStatusMessage msg = new AbilityStatusMessage(CombatClient.MSG_TYPE_ABILITY_STATUS, player.getOid(), event.getPropertyMap());
    Engine.getAgent().sendBroadcast((Message)msg);
  }
 
  protected void processLogout(ClientConnection con, LogoutEvent event) {}
 
  protected void processSceneLoaded(ClientConnection con, SceneLoadedEvent event) {
    Player player = (Player)con.getAssociation();
    player.sceneLoading(false);
    if (Log.loggingDebug)
      Log.debug("SCENE: sceneLoading set to false for player: " + player.getOid());
  }
 
  protected void processExtensionMessageEvent(ClientConnection con, ExtensionMessageEvent event) {
    String key = (String)event.getPropertyMap().get("ext_msg_subtype");
    OID target = event.getTargetOid();
    Player player = (Player)con.getAssociation();
    if (Log.loggingDebug)
      Log.debug("processExtensionMessageEvent: " + player + " subType=" + key + " target=" + target);
    List<ProxyExtensionHook> proxyHookList = this.extensionHooks.get(key);
    if (proxyHookList != null) {
      for (ProxyExtensionHook hook : proxyHookList)
        hook.processExtensionEvent(event, player, this);
      return;
    }
    if (target != null) {
      WorldManagerClient.TargetedExtensionMessage msg = new WorldManagerClient.TargetedExtensionMessage(WorldManagerClient.MSG_TYPE_EXTENSION, target, player.getOid(), event.getClientTargeted(), event.getPropertyMap());
      if (event.getClientTargeted().booleanValue()) {
        msg.setMsgType(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
        if (allowClientToClientMessage(player, target, msg))
          Engine.getAgent().sendBroadcast((Message)msg);
      } else {
        MessageType msgType = getExtensionMessageType(key);
        if (msgType == null) {
          Log.error("processExtensionMessageEvent: key '" + key + "' has no corresponding MessageType");
          return;
        }
        msg.setMsgType(msgType);
        Engine.getAgent().sendBroadcast((Message)msg);
      }
    } else {
      MessageType msgType = getExtensionMessageType(key);
      if (msgType == null) {
        Log.error("processExtensionMessageEvent: key '" + key + "' has no corresponding MessageType");
        return;
      }
      WorldManagerClient.ExtensionMessage msg = new WorldManagerClient.ExtensionMessage(msgType, player.getOid(), event.getPropertyMap());
      Engine.getAgent().sendBroadcast((Message)msg);
    }
  }
 
  public void registerExtensionSubtype(String subtype, MessageType type) {
    this.extensionMessageRegistry.put(subtype, type);
  }
 
  public MessageType unregisterExtensionSubtype(String subtype) {
    return this.extensionMessageRegistry.remove(subtype);
  }
 
  public MessageType getExtensionMessageType(String subtype) {
    return this.extensionMessageRegistry.get(subtype);
  }
 
  public boolean allowClientToClientMessage(Player sender, OID targetOid, WorldManagerClient.TargetedExtensionMessage message) {
    return this.defaultAllowClientToClientMessage;
  }
 
  protected boolean specialCaseNewProcessing(PerceptionMessage.ObjectNote objectNote, Player player) {
    long start = System.currentTimeMillis();
    ClientConnection con = player.getConnection();
    OID objOid = objectNote.getSubject();
    ObjectType objType = objectNote.getObjectType();
    if (objType == ObjectTypes.light) {
      Log.debug("specialCaseNewProcessing: got a light object");
      LightData lightData = (LightData)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, Light.LightDataPropertyKey);
      if (Log.loggingDebug)
        Log.debug("specialCaseNewProcessing: light data=" + lightData);
      NewLightEvent lightEvent = new NewLightEvent(player.getOid(), objOid, lightData);
      con.send(lightEvent.toBytes());
      return true;
    }
    if (objType.equals(WorldManagerClient.TEMPL_OBJECT_TYPE_TERRAIN_DECAL)) {
      Log.debug("specialCaseNewProcessing: got a terrain decal object");
      TerrainDecalData decalData = (TerrainDecalData)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
      if (Log.loggingDebug)
        Log.debug("specialCaseNewProcessing: terrain decal data=" + decalData);
      NewTerrainDecalEvent decalEvent = new NewTerrainDecalEvent(objOid, decalData);
      con.send(decalEvent.toBytes());
      return true;
    }
    if (objType.equals(WorldManagerClient.TEMPL_OBJECT_TYPE_POINT_SOUND)) {
      Log.debug("specialCaseNewProcessing: got a point sound object");
      List<SoundData> soundData = (List<SoundData>)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, WorldManagerClient.TEMPL_SOUND_DATA_LIST);
      if (Log.loggingDebug)
        Log.debug("specialCaseNewProcessing: sound data=" + soundData);
      WorldManagerClient.SoundMessage soundMsg = new WorldManagerClient.SoundMessage(objOid);
      soundMsg.setSoundData(soundData);
      con.send(soundMsg.toBuffer());
      return true;
    }
    WorldManagerClient.PerceptionInfo perceptionInfo = (WorldManagerClient.PerceptionInfo)objectNote.getObjectInfo();
    if (perceptionInfo.objectInfo == null)
      return true;
    WorldManagerClient.MobPathMessage pathMsg = (WorldManagerClient.MobPathMessage)perceptionInfo.objectInfo.getProperty(WorldManagerClient.MOB_PATH_PROPERTY);
    if (Log.loggingDebug)
      Log.debug("INFO: MobPathMessage special case with player/npc: " + perceptionInfo.objectInfo.name);
    con.send(perceptionInfo.objectInfo.toBuffer(player.getOid()));
    if (Log.loggingDebug)
      Log.debug("INFO: specialCaseNewProcessing " + perceptionInfo.displayContext);
    if (perceptionInfo.displayContext != null) {
      ModelInfoEvent modelInfoEvent = new ModelInfoEvent(objOid);
      modelInfoEvent.setDisplayContext(perceptionInfo.displayContext);
      con.send(modelInfoEvent.toBytes());
    } else if (Log.loggingDebug) {
      Log.debug("No display context for " + objOid + " " + perceptionInfo.objectInfo);
    }
    if (pathMsg != null)
      if (pathMsg.pathExpired()) {
        if (Log.loggingDebug)
          Log.debug("specialCaseNewProcessing: for mob " + objOid + ", last mob path expired " + pathMsg.toString());
      } else {
        if (Log.loggingDebug)
          Log.debug("specialCaseNewProcessing: for mob " + objOid + ", sending last mob path " + pathMsg.toString());
        AOByteBuffer pathBuf = pathMsg.toBuffer();
        con.send(pathBuf);
      } 
    Map<String, DisplayContext> childMap = null;
    if (perceptionInfo.displayContext != null)
      childMap = perceptionInfo.displayContext.getChildDCMap();
    if (childMap != null && !childMap.isEmpty()) {
      for (String slot : childMap.keySet()) {
        DisplayContext attachDC = childMap.get(slot);
        if (attachDC == null)
          throw new AORuntimeException("attach DC is null for obj: " + objOid);
        OID attacheeOID = attachDC.getObjRef();
        if (attacheeOID == null)
          throw new AORuntimeException("attachee oid is null for obj: " + objOid);
        if (Log.loggingDebug)
          Log.debug("specialCaseNewProcessing: sending attach message to " + player.getOid() + " attaching to obj " + objOid + ", object being attached=" + attacheeOID + " to slot " + slot + ", attachmentDC=" + attachDC);
        AttachEvent event = new AttachEvent(objOid, attacheeOID, slot, attachDC);
        con.send(event.toBytes());
      }
      if (Log.loggingDebug)
        Log.debug("specialCaseNewProcessing: done with processing attachments");
    }
    long finish = System.currentTimeMillis();
    if (Log.loggingDebug)
      Log.debug("specialCaseNewProcessing: finished.\tplayerOid=" + player.getOid() + ", oid=" + objOid + " in " + (finish - start) + " ms");
    return false;
  }
 
  protected boolean specialCaseFreeProcessing(PerceptionMessage.ObjectNote objectNote, Player player) {
    if (player.getOid().equals(objectNote.getSubject())) {
      Log.debug("ignoring free object message to self");
      return true;
    }
    ClientConnection con = player.getConnection();
    if (!con.isOpen())
      con = null;
    OID objOid = objectNote.getSubject();
    if (objectNote.getObjectType() == ObjectTypes.road) {
      if (Log.loggingDebug)
        Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", roadSegmentOid=" + objOid);
      handleFreeRoad(con, objOid);
      return true;
    }
    if (objectNote.getObjectType().equals(WorldManagerClient.TEMPL_OBJECT_TYPE_TERRAIN_DECAL)) {
      if (Log.loggingDebug)
        Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", decalOid=" + objOid);
      FreeTerrainDecalEvent decalEvent = new FreeTerrainDecalEvent(objOid);
      if (con != null)
        con.send(decalEvent.toBytes());
      return true;
    }
    if (Log.loggingDebug)
      Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", objOid=" + objOid);
    NotifyFreeObjectEvent freeEvent = new NotifyFreeObjectEvent(player.getOid(), objOid);
    if (con != null)
      con.send(freeEvent.toBytes());
    return false;
  }
 
  protected void handleFreeRoad(ClientConnection con, OID objOid) {
    WorldManagerClient.FreeRoadMessage freeRoadMsg = new WorldManagerClient.FreeRoadMessage(objOid);
    AOByteBuffer buf = freeRoadMsg.toBuffer();
    if (con != null)
      con.send(buf);
  }
 
  public static void addStaticPerception(OID playerOid, OID oid) {
    addStaticPerception(playerOid, oid, null, null, false);
  }
 
  public static void addStaticPerception(OID oid, OID oid2, String name, ObjectType type) {
    addStaticPerception(oid, oid2, name, type, true);
  }
 
  private static void addStaticPerception(OID playerOid, OID oid, String name, ObjectType type, boolean hasObjectInfo) {
    AddStaticPerceptionMessage message = new AddStaticPerceptionMessage(MSG_TYPE_ADD_STATIC_PERCEPTION);
    message.setTarget(playerOid);
    message.setSubject(oid);
    message.setName(name);
    message.setType(type);
    message.setHasObjectInfo(hasObjectInfo);
    Engine.getAgent().sendBroadcast((Message)message);
  }
 
  public static void removeStaticPerception(OID playerOid, OID oid) {
    TargetMessage message = new TargetMessage(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
    message.setTarget(playerOid);
    message.setSubject(oid);
    Engine.getAgent().sendBroadcast((Message)message);
  }
 
  protected void processPlayerIgnoreList(Player player) {
    if (player.getStatus() == 3) {
      Log.error("ProxyPlugin.processPlayerIgnoreList: Aborting... player.getStatus() is STATUS_LOGOUT");
      return;
    }
    sendPlayerIgnoreList(player);
  }
 
  protected void sendPlayerIgnoreList(Player player) {
    String missing = " Missing ";
  }
 
  public void updateIgnoredOids(Player player, List<OID> nowIgnored, List<OID> noLongerIgnored) {}
 
  public List<Object> matchingPlayers(Player player, String playerName, Boolean exactMatch) {
    boolean match = (exactMatch == null) ? true : exactMatch.booleanValue();
    List<Object> matchLists = Engine.getDatabase().getOidsAndNamesMatchingName(playerName, match);
    List<OID> oids = (List<OID>)matchLists.get(0);
    List<String> names = (List<String>)matchLists.get(1);
    if (Log.loggingDebug)
      log.debug("ProxyPlugin.matchingPlayers: For player " + player.getOid() + ", found " + ((oids == null) ? 0 : oids.size()) + " players: " + Database.makeOidCollectionString(oids) + " " + (match ? "exactly matching" : "starting with") + " name '" + playerName + "':" + Database.makeNameCollectionString(names));
    return matchLists;
  }
 
  public boolean isOnBlockList2(OID playerOid, OID targetOid) {
    if (Log.loggingDebug)
      log.debug("IsOnBlockList: SocialPlugin  started for: " + playerOid);
    boolean isOnBlockList = this.aDB.isOnBlackList(playerOid, targetOid);
    if (isOnBlockList) {
      String targetName = (WorldManagerClient.getObjectInfo(targetOid)).name;
      EventMessageHelper.SendErrorEvent(playerOid, "ErrorPlayerOnBlockList", 0, targetName);
    } else {
      isOnBlockList = this.aDB.isOnBlackList(targetOid, playerOid);
      if (isOnBlockList) {
        String targetName = (WorldManagerClient.getObjectInfo(targetOid)).name;
        EventMessageHelper.SendErrorEvent(playerOid, "ErrorPlayerYourOnBlockList", 0, targetName);
      }
    }
    if (Log.loggingDebug)
      log.debug("IsOnBlockList: SocialPlugin  finished for: " + playerOid);
    return isOnBlockList;
  }
 
  private boolean isPlayerConnectionValid(Player player) {
    ClientConnection con = player.getConnection();
    return (con != null && con.isOpen());
  }
 
  public static OID handleFullInstance(int instanceTemplateID, InstanceClient.InstanceInfo instanceInfo) {
    OID instanceOid;
    if (Log.loggingDebug)
      Log.debug("POP: instance full with template: " + instanceTemplateID);
    int instanceNum = 1;
    String instanceName = "";
    InstanceTemplate island = InstanceClient.getInstanceTemplate(instanceTemplateID);
    while (true) {
      instanceName = island.getName() + "_" + instanceNum;
      instanceOid = InstanceClient.getInstanceOid(instanceName);
      if (instanceOid != null) {
        instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145);
        if (instanceInfo.populationLimit < 1 || instanceInfo.playerPopulation < instanceInfo.populationLimit)
          break;
      } else {
        Template overrideTemplate = new Template();
        overrideTemplate.put(Namespace.INSTANCE, "name", instanceName);
        overrideTemplate.setName(instanceName);
        instanceOid = InstanceClient.createInstance(instanceTemplateID, overrideTemplate);
        if (instanceOid != null)
          break;
      }
      instanceNum++;
    }
    return instanceOid;
  }
 
  private void updateInstancePerception(OID playerOid, OID prevInstanceOid, OID destInstanceOid, String destInstanceName) {
    if (prevInstanceOid != null)
      removeStaticPerception(playerOid, prevInstanceOid);
    addStaticPerception(playerOid, destInstanceOid, destInstanceName, ObjectTypes.instance);
  }
 
  protected void pushInstanceRestorePoint(Player player, BasicWorldNode loc) {
    OID playerOid = player.getOid();
    if (Log.loggingDebug)
      log.debug("pushInstanceRestorePoint " + playerOid);
    InstanceRestorePoint restorePoint = new InstanceRestorePoint();
    restorePoint.setInstanceOid(loc.getInstanceOid());
    restorePoint.setLoc(loc.getLoc());
    restorePoint.setOrientation(loc.getOrientation());
    InstanceClient.InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(loc.getInstanceOid(), 8);
    restorePoint.setInstanceID(instanceInfo.templateID);
    LinkedList<Object> restoreStack = (LinkedList<Object>)EnginePlugin.getObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack");
    if (restoreStack == null)
      restoreStack = new LinkedList();
    restoreStack.add(restorePoint);
    EnginePlugin.setObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack", restoreStack);
  }
 
  protected void sendOceanData(OceanData oceanData, Player player) {
    ClientParameter.ClientParameterMessage clientParameterMessage = new ClientParameter.ClientParameterMessage(player.getOid());
    clientParameterMessage.setProperty("Ocean.DisplayOcean", oceanData.displayOcean.toString());
    if (oceanData.useParams != null)
      clientParameterMessage.setProperty("Ocean.UseParams", oceanData.useParams.toString());
    if (oceanData.waveHeight != null)
      clientParameterMessage.setProperty("Ocean.WaveHeight", oceanData.waveHeight.toString());
    if (oceanData.seaLevel != null)
      clientParameterMessage.setProperty("Ocean.SeaLevel", oceanData.seaLevel.toString());
    if (oceanData.bumpScale != null)
      clientParameterMessage.setProperty("Ocean.BumpScale", oceanData.bumpScale.toString());
    if (oceanData.bumpSpeedX != null)
      clientParameterMessage.setProperty("Ocean.BumpSpeedX", oceanData.bumpSpeedX.toString());
    if (oceanData.bumpSpeedZ != null)
      clientParameterMessage.setProperty("Ocean.BumpSpeedZ", oceanData.bumpSpeedZ.toString());
    if (oceanData.textureScaleX != null)
      clientParameterMessage.setProperty("Ocean.TextureScaleX", oceanData.textureScaleX.toString());
    if (oceanData.textureScaleZ != null)
      clientParameterMessage.setProperty("Ocean.TextureScaleZ", oceanData.textureScaleZ.toString());
    if (oceanData.deepColor != null)
      clientParameterMessage.setProperty("Ocean.DeepColor", oceanData.deepColor.toString());
    if (oceanData.shallowColor != null)
      clientParameterMessage.setProperty("Ocean.ShallowColor", oceanData.shallowColor.toString());
    player.getConnection().send(clientParameterMessage.toBuffer(player.getVersion()));
  }
 
  protected Player verifyPlayer(String context, Event event, ClientConnection con) {
    Player player = (Player)con.getAssociation();
    if (!player.getOid().equals(event.getObjectOid()))
      throw new AORuntimeException(context + ": con doesn't match player " + player + " against eventOid " + event.getObjectOid());
    return player;
  }
 
  public void incrementChatCount() {
    this.chatSentCount++;
  }
 
  public void incrementPrivateChatCount() {
    this.privateChatSentCount++;
  }
 
  protected static final Logger log = new Logger("ProxyPlugin");
 
  PlayerMessageCallback playerMessageCallback;
 
  protected PlayerManager playerManager;
 
  protected ConcurrentHashMap<OID, String> playersOnlineList;
 
  protected ConcurrentHashMap<OID, String> playersOnlineOnProxy;
 
  protected TimeHistogram proxyQueueHistogram;
 
  protected TimeHistogram proxyCallbackHistogram;
 
  protected List<MessageType> extraPlayerMessageTypes;
 
  private ProxyLoginCallback proxyLoginCallback;
 
  private InstanceEntryCallback instanceEntryCallback;
 
  private int instanceEntryCount;
 
  private int chatSentCount;
 
  private int privateChatSentCount;
 
  public static final MessageType MSG_TYPE_VOICE_PARMS = MessageType.intern("ao.VOICE_PARMS");
 
  public static final MessageType MSG_TYPE_PLAYER_PATH_REQ = MessageType.intern("ao.PLAYER_PATH_REQ");
 
  public static final MessageType MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST = MessageType.intern("ao.UPDATE_PLAYER_IGNORE_LIST");
 
  public static final MessageType MSG_TYPE_GET_MATCHING_PLAYERS = MessageType.intern("ao.GET_MATCHING_PLAYERS");
 
  public static final MessageType MSG_TYPE_PLAYER_IGNORE_LIST = MessageType.intern("ao.PLAYER_IGNORE_LIST");
 
  public static final MessageType MSG_TYPE_PLAYER_IGNORE_LIST_REQ = MessageType.intern("ao.PLAYER_IGNORE_LIST_REQ");
 
  public static final MessageType MSG_TYPE_RELAY_UPDATE_PLAYER_IGNORE_LIST = MessageType.intern("ao.RELAY_UPDATE_PLAYER_IGNORE_LIST");
 
  public static final MessageType MSG_TYPE_GET_PLAYER_LOGIN_STATUS = MessageType.intern("ao.GET_PLAYER_LOGIN_STATUS");
 
  public static final MessageType MSG_TYPE_LOGOUT_PLAYER = MessageType.intern("ao.LOGOUT_PLAYER");
 
  public static final MessageType MSG_TYPE_ADD_STATIC_PERCEPTION = MessageType.intern("ao.ADD_STATIC_PERCEPTION");
 
  public static final MessageType MSG_TYPE_REMOVE_STATIC_PERCEPTION = MessageType.intern("ao.REMOVE_STATIC_PERCEPTION");
 
  public static final MessageType MSG_TYPE_LOGIN_SPAWNED = MessageType.intern("ao.LOGIN_SPAWNED");
 
  public static final MessageType MSG_TYPE_ACCOUNT_LOGIN = MessageType.intern("ao.ACCOUNT_LOGIN");
 
  public static final MessageType MSG_TYPE_SERVER_SHUTDOWN_MESSAGE = MessageType.intern("server.Shutdown_Message");
 
  public static final MessageType MSG_TYPE_SERVER_SHUTDOWN = MessageType.intern("server.Shutdown");
 
  public static final MessageType MSG_TYPE_SERVER_RELOAD = MessageType.intern("server.Reload");
 
  protected static String voiceServerHost = "";
 
  protected static Integer voiceServerPort = null;
 
  public String serverCapabilitiesSentToClient;
 
  public static int DiffTimeToSkipDirLocOrientMessage = 500;
 
  static int serverSocketReceiveBufferSize = 8388608;
 
  public static int MaxConcurrentUsers = 2000;
 
  public static int restriction_level = 0;
 
  public static int idleTimeout = 900;
 
  public static int silenceTimeout = 30;
 
  public static int silenceLoadingTimeout = 900;
 
  public static int maxMessagesBeforeConnectionReset = 2000;
 
  public static int maxByteCountBeforeConnectionReset = 1000000;
 
  public String capacityError;
 
  public String tokenError;
 
  public static String SpeedhackChatMsg = "Detected Speedhack";
 
  public static int SpeedhackCountToDisconect = 10;
 
  public static int SpeedhackMinDiff = 8000;
 
  private ClientTCPMessageIO clientTCPMessageIO;
 
  Set<OID> adminSet;
 
  Map<OID, ClientConnection> clientConnections;
 
  Set<String> filteredProps;
 
  Set<String> playerSpecificProps;
 
  Set<String> cachedPlayerSpecificFilterProps;
 
  String serverVersion;
 
  protected Map<String, List<ProxyExtensionHook>> extensionHooks;
 
  private int connectionLimit;
 
  boolean devMode;
 
  public void addAdmin(OID oid) {
    if (Log.loggingDebug)
      log.debug("ProxyPlugin.addAdmin: adding oid " + oid);
    this.lock.lock();
    try {
      this.adminSet.add(oid);
    } finally {
      this.lock.unlock();
    }
  }
 
  public Set<OID> getAdmins() {
    this.lock.lock();
    try {
      return new HashSet<>(this.adminSet);
    } finally {
      this.lock.unlock();
    }
  }
 
  public boolean isAdmin(OID playerOid) {
    this.lock.lock();
    try {
      if (playerOid == null)
        return false;
      AccountDatabase aDB = new AccountDatabase(false);
      int status = aDB.getCharacterAccountStatus(playerOid);
      return (status == 5);
    } finally {
      this.lock.unlock();
    }
  }
 
  public int GetConnectionLimit() {
    return this.connectionLimit;
  }
 
  protected Object createMBeanInstance() {
    return new ProxyJMX(this);
  }
 
  private String getTemp() {
    return "47bedc488b0106b2219dd2e2ff5524fd";
  }
}
 
а ет декомпил ровный?
Java:
import atavism.agis.database.AccountDatabase;
import atavism.agis.database.ContentDatabase;
import atavism.agis.events.AbilityStatusEvent;
import atavism.agis.events.AbilityStatusMessage;
import atavism.agis.events.ConcludeQuest;
import atavism.agis.events.QuestResponse;
import atavism.agis.events.RequestQuestInfo;
import atavism.agis.plugins.AnimationClient;
import atavism.agis.plugins.ChatClient;
import atavism.agis.plugins.CombatClient;
import atavism.agis.plugins.DataLoggerClient;
import atavism.agis.plugins.QuestClient;
import atavism.agis.plugins.SocialClient;
import atavism.agis.util.EventMessageHelper;
import atavism.agis.util.HelperFunctions;
import atavism.management.Management;
import atavism.msgsys.FilterUpdate;
import atavism.msgsys.IFilter;
import atavism.msgsys.Message;
import atavism.msgsys.MessageCallback;
import atavism.msgsys.MessageTrigger;
import atavism.msgsys.MessageType;
import atavism.msgsys.MessageTypeFilter;
import atavism.msgsys.NoRecipientsException;
import atavism.msgsys.RPCTimeoutException;
import atavism.msgsys.ResponseCallback;
import atavism.msgsys.SubjectMessage;
import atavism.msgsys.TargetMessage;
import atavism.server.engine.BasicWorldNode;
import atavism.server.engine.Database;
import atavism.server.engine.Engine;
import atavism.server.engine.EnginePlugin;
import atavism.server.engine.Event;
import atavism.server.engine.Hook;
import atavism.server.engine.Namespace;
import atavism.server.engine.OID;
import atavism.server.events.ActivateItemEvent;
import atavism.server.events.AttachEvent;
import atavism.server.events.AuthorizedLoginEvent;
import atavism.server.events.AuthorizedLoginResponseEvent;
import atavism.server.events.AutoAttackEvent;
import atavism.server.events.ComEvent;
import atavism.server.events.CommandEvent;
import atavism.server.events.DirLocOrientEvent;
import atavism.server.events.ExtensionMessageEvent;
import atavism.server.events.FreeTerrainDecalEvent;
import atavism.server.events.LoadingStateEvent;
import atavism.server.events.LogoutEvent;
import atavism.server.events.ModelInfoEvent;
import atavism.server.events.NewLightEvent;
import atavism.server.events.NewTerrainDecalEvent;
import atavism.server.events.NotifyFreeObjectEvent;
import atavism.server.events.PlayerHaEvent;
import atavism.server.events.SceneLoadedEvent;
import atavism.server.events.WorldFileEvent;
import atavism.server.math.Point;
import atavism.server.messages.LoginMessage;
import atavism.server.messages.LogoutMessage;
import atavism.server.messages.PerceptionFilter;
import atavism.server.messages.PerceptionMessage;
import atavism.server.messages.PerceptionTrigger;
import atavism.server.messages.PropertyMessage;
import atavism.server.network.AOByteBuffer;
import atavism.server.network.ClientConnection;
import atavism.server.network.ClientTCPMessageIO;
import atavism.server.network.PacketAggregator;
import atavism.server.network.rdp.RDPServer;
import atavism.server.network.rdp.RDPServerSocket;
import atavism.server.objects.DisplayContext;
import atavism.server.objects.InstanceEntryCallback;
import atavism.server.objects.InstanceRestorePoint;
import atavism.server.objects.InstanceTemplate;
import atavism.server.objects.Light;
import atavism.server.objects.LightData;
import atavism.server.objects.ObjectType;
import atavism.server.objects.ObjectTypes;
import atavism.server.objects.OceanData;
import atavism.server.objects.Player;
import atavism.server.objects.PlayerManager;
import atavism.server.objects.ProxyExtensionHook;
import atavism.server.objects.ProxyLoginCallback;
import atavism.server.objects.SoundData;
import atavism.server.objects.Template;
import atavism.server.objects.TerrainDecalData;
import atavism.server.objects.World;
import atavism.server.plugins.ClientParameter;
import atavism.server.plugins.InstanceClient;
import atavism.server.plugins.InventoryClient;
import atavism.server.plugins.ObjectManagerClient;
import atavism.server.plugins.ProxyPlugin;
import atavism.server.plugins.WorldManagerClient;
import atavism.server.telemetry.Prometheus;
import atavism.server.util.AOMeter;
import atavism.server.util.AORuntimeException;
import atavism.server.util.Base64;
import atavism.server.util.CountLogger;
import atavism.server.util.DebugUtils;
import atavism.server.util.EncryptionHelper;
import atavism.server.util.LockFactory;
import atavism.server.util.Log;
import atavism.server.util.Logger;
import atavism.server.util.ObjectLockManager;
import atavism.server.util.SQCallback;
import atavism.server.util.SQThreadPool;
import atavism.server.util.SecureToken;
import atavism.server.util.SecureTokenManager;
import atavism.server.util.ServerVersion;
import atavism.server.util.SquareQueue;
import atavism.server.util.TimeHistogram;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.Timer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.function.Supplier;

public class ProxyPlugin extends EnginePlugin implements ClientConnection.AcceptCallback, ClientConnection.MessageCallback {
  private static int MESSAGE_QUEUE_THREADS = 16;
 
  private static int EVENT_QUEUE_THREADS = 16;
 
  private static int SLOW_EVENT_QUEUE_THREADS = 8;
 
  private static final int RDP_CHANNELS_COUNT = 128;
 
  public static final int PERCEPTION_GAIN_THRESHOLD = 20;
 
  CountLogger countLogger;
 
  CountLogger.Counter countMsgPerception;
 
  CountLogger.Counter countMsgPerceptionGain;
 
  CountLogger.Counter countMsgPerceptionLost;
 
  CountLogger.Counter countMsgUpdateWNodeIn;
 
  CountLogger.Counter countMsgUpdateWNodeOut;
 
  CountLogger.Counter countMsgPropertyIn;
 
  CountLogger.Counter countMsgPropertyOut;
 
  CountLogger.Counter countMsgTargetedProperty;
 
  CountLogger.Counter countMsgWNodeCorrectIn;
 
  CountLogger.Counter countMsgWNodeCorrectOut;
 
  CountLogger.Counter countMsgMobPathIn;
 
  CountLogger.Counter countMsgMobPathOut;
 
  public ProxyPlugin() {
    super(getPluginName(), null);
    this.countLogger = new CountLogger("ProxyMsg", 5000, 2);
    this.commandMapLock = LockFactory.makeLock("CommandMapLock");
    this.commandMap = new HashMap<>();
    this.defaultCommandAccess = (CommandAccessCheck)new DefaultCommandAccess(null);
    this.messageQQ = new SquareQueue("Message");
    this.messageThreadPool = null;
    this.eventQQ = new SquareQueue("Event");
    this.eventThreadPool = null;
    this.slowEventQQ = new SquareQueue("SlowEvent");
    this.slowEventThreadPool = null;
    this.clientMsgMeter = new AOMeter("ClientEventProcessorMeter");
    this.playerLastClientTime = new ConcurrentHashMap<>();
    this.playerLastServerTime = new ConcurrentHashMap<>();
    this.playerFirstSpeedHackTime = new ConcurrentHashMap<>();
    this.playerSpeedHackCount = new ConcurrentHashMap<>();
    this.defaultAllowClientToClientMessage = false;
    this.extensionMessageRegistry = new HashMap<>();
    this.logoutExecutor = Executors.newCachedThreadPool();
    this.playerMessageCallback = new PlayerMessageCallback(this);
    this.playerManager = new PlayerManager();
    this.playersOnlineList = new ConcurrentHashMap<>();
    this.playersOnlineOnProxy = new ConcurrentHashMap<>();
    this.proxyQueueHistogram = null;
    this.proxyCallbackHistogram = null;
    this.extraPlayerMessageTypes = null;
    this.proxyLoginCallback = (ProxyLoginCallback)new DefaultProxyLoginCallback(null);
    this.instanceEntryCallback = (InstanceEntryCallback)new DefaultInstanceEntryCallback(null);
    this.instanceEntryCount = 0;
    this.chatSentCount = 0;
    this.privateChatSentCount = 0;
    this.serverCapabilitiesSentToClient = "DirLocOrient";
    this.capacityError = "Login Failed: Servers at capacity, please try again later.";
    this.tokenError = "Login Failed: Secure token invalid.";
    this.clientTCPMessageIO = null;
    this.adminSet = new HashSet<>();
    this.clientConnections = new ConcurrentHashMap<>();
    this.filteredProps = null;
    this.playerSpecificProps = null;
    this.cachedPlayerSpecificFilterProps = null;
    this.serverVersion = null;
    this.extensionHooks = new HashMap<>();
    this.connectionLimit = 0;
    this.devMode = true;
    setPluginType("Proxy");
    this.serverVersion = "10.7.0 " + ServerVersion.getBuildNumber();
    String MessageQueueThreadPoolSize = Engine.properties.getProperty("atavism.proxy.MessageQueueThreadPoolSize");
    if (MessageQueueThreadPoolSize != null)
      try {
        int v = Integer.parseInt(MessageQueueThreadPoolSize);
        MESSAGE_QUEUE_THREADS = v;
      } catch (NumberFormatException e) {
        e.printStackTrace();
        Log.exception(e);
      }
    String EventQueueThreadPoolSize = Engine.properties.getProperty("atavism.proxy.EventQueueThreadPoolSize");
    if (EventQueueThreadPoolSize != null)
      try {
        int v = Integer.parseInt(EventQueueThreadPoolSize);
        EVENT_QUEUE_THREADS = v;
      } catch (NumberFormatException e) {
        e.printStackTrace();
        Log.exception(e);
      }
    String proxy_concurrent_logins = Engine.properties.getProperty("atavism.proxy.ConcurrentLogins");
    if (proxy_concurrent_logins != null)
      try {
        int v = Integer.parseInt(proxy_concurrent_logins);
        SLOW_EVENT_QUEUE_THREADS = v;
      } catch (NumberFormatException e) {
        e.printStackTrace();
        Log.exception(e);
      }
    this.messageThreadPool = new SQThreadPool(this.messageQQ, (SQCallback)new MessageCallback(this, this), MESSAGE_QUEUE_THREADS);
    this.eventThreadPool = new SQThreadPool(this.eventQQ, (SQCallback)new EventCallback(this), EVENT_QUEUE_THREADS);
    this.slowEventThreadPool = new SQThreadPool(this.slowEventQQ, (SQCallback)new EventCallback(this), SLOW_EVENT_QUEUE_THREADS);
    this.countMsgPerception = this.countLogger.addCounter("ao.PERCEPTION_INFO");
    this.countMsgPerceptionGain = this.countLogger.addCounter("Perception.gain");
    this.countMsgPerceptionLost = this.countLogger.addCounter("Perception.lost");
    this.countMsgUpdateWNodeIn = this.countLogger.addCounter("ao.UPDATEWNODE.in");
    this.countMsgUpdateWNodeOut = this.countLogger.addCounter("ao.UPDATEWNODE.out");
    this.countMsgPropertyIn = this.countLogger.addCounter("ao.PROPERTY.in");
    this.countMsgPropertyOut = this.countLogger.addCounter("ao.PROPERTY.out");
    this.countMsgTargetedProperty = this.countLogger.addCounter("ao.TARGETED_PROPERTY");
    this.countMsgWNodeCorrectIn = this.countLogger.addCounter("ao.WNODECORRECT.in");
    this.countMsgWNodeCorrectOut = this.countLogger.addCounter("ao.WNODECORRECT.out");
    this.countMsgMobPathIn = this.countLogger.addCounter("ao.MOB_PATH.in");
    this.countMsgMobPathOut = this.countLogger.addCounter("ao.MOB_PATH.out");
    ContentDatabase ctDB = new ContentDatabase(false);
    String _silenceTimeout = ctDB.loadGameSetting("PLAYER_SILENCE_TIMEOUT");
    if (_silenceTimeout != null)
      silenceTimeout = Integer.parseInt(_silenceTimeout);
    this.aDB = new AccountDatabase(true);
    addProxyExtensionHook("ao.heartbeat", (ProxyExtensionHook)new PlayerHeartbeat(null));
    (new Thread((Runnable)new PlayerTimeout(this, null), "PlayerTimeout")).start();
  }
 
  private static String getPluginName() {
    String proxyPluginName;
    try {
      proxyPluginName = Engine.getAgent().getDomainClient().allocName("PLUGIN", "Proxy#");
    } catch (IOException e) {
      throw new AORuntimeException("Could not allocate proxy plugin name", e);
    }
    return proxyPluginName;
  }
 
  public static boolean isOnBlockList(OID subject, OID target) {
    WorldManagerClient.ExtensionMessage message = new WorldManagerClient.ExtensionMessage(SocialClient.MSG_TYPE_IS_ON_BLOCK_LIST, "ao.IS_ON_BLOCK_LIST", subject);
    message.setProperty("targetOid", (Serializable)target);
    return Engine.getAgent().sendRPCReturnBoolean((Message)message).booleanValue();
  }
 
  public boolean isDevMode() {
    return this.devMode;
  }
 
  public void setDevMode(boolean mode) {
    this.devMode = mode;
  }
 
  public List<MessageType> getExtraPlayerMessageTypes() {
    return this.extraPlayerMessageTypes;
  }
 
  public void setExtraPlayerMessageTypes(List<MessageType> extraPlayerMessageTypes) {
    this.extraPlayerMessageTypes = extraPlayerMessageTypes;
  }
 
  public void addExtraPlayerMessageType(MessageType messageType) {
    if (this.extraPlayerMessageTypes == null)
      this.extraPlayerMessageTypes = new LinkedList<>();
    this.extraPlayerMessageTypes.add(messageType);
  }
 
  public void addExtraPlayerExtensionMessageType(MessageType messageType) {
    addExtraPlayerMessageType(messageType);
    getHookManager().addHook(messageType, (Hook)new ExtensionHook(this));
  }
 
  public void addProxyExtensionHook(String subType, ProxyExtensionHook hook) {
    synchronized (this.extensionHooks) {
      List<ProxyExtensionHook> hookList = this.extensionHooks.get(subType);
      if (hookList == null) {
        hookList = new ArrayList<>();
        this.extensionHooks.put(subType, hookList);
      }
      hookList.add(hook);
    }
  }
 
  public Map<String, List<ProxyExtensionHook>> getProxyExtensionHooks(String subType) {
    return this.extensionHooks;
  }
 
  public void onActivate() {
    try {
      PacketAggregator.initializeAggregation(Engine.getProperties());
      String logProxyHistograms = Engine.properties.getProperty("atavism.log_proxy_histograms");
      if (logProxyHistograms != null && logProxyHistograms.equals("true")) {
        int interval = 5000;
        String intervalString = Engine.properties.getProperty("atavism.log_proxy_histograms_interval");
        if (intervalString != null) {
          int newInterval = Integer.parseInt(intervalString);
          if (newInterval > 0)
            interval = newInterval;
        }
        this.proxyQueueHistogram = new TimeHistogram("TimeInQ", Integer.valueOf(interval));
        this.proxyCallbackHistogram = new TimeHistogram("TimeInCallback", Integer.valueOf(interval));
        this.countLogger.start();
      }
      this.filteredProps = new HashSet<>();
      this.playerSpecificProps = new HashSet<>();
      this.cachedPlayerSpecificFilterProps = new HashSet<>();
      addFilteredProperty("inv.bag");
      addFilteredProperty(":loc");
      addFilteredProperty("masterOid");
      addFilteredProperty("agisobj.basedc");
      addFilteredProperty("aoobj.dc");
      addFilteredProperty("aoobj.followsterrainflag");
      addFilteredProperty("aoobj.perceiver");
      addFilteredProperty("aoobj.scale");
      addFilteredProperty("aoobj.mobflag");
      addFilteredProperty("aoobj.structflag");
      addFilteredProperty("aoobj.userflag");
      addFilteredProperty("aoobj.itemflag");
      addFilteredProperty("aoobj.lightflag");
      addFilteredProperty("namespace");
      addFilteredProperty("regenEffectMap");
      addFilteredProperty(WorldManagerClient.MOB_PATH_PROPERTY);
      addFilteredProperty(WorldManagerClient.TEMPL_SOUND_DATA_LIST);
      addFilteredProperty(WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
      addFilteredProperty("instanceStack");
      addFilteredProperty("currentInstanceName");
      addFilteredProperty("ignored_oids");
      registerHooks();
      PluginMessageCallback pluginMessageCallback = new PluginMessageCallback(this);
      MessageTypeFilter filter = new MessageTypeFilter();
      filter.addType(WorldManagerClient.MSG_TYPE_SYS_CHAT);
      Engine.getAgent().createSubscription((IFilter)filter, (MessageCallback)pluginMessageCallback);
      LinkedList<MessageType> types = new LinkedList<>();
      types.add(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO);
      types.add(WorldManagerClient.MSG_TYPE_ANIMATION);
      types.add(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT);
      types.add(WorldManagerClient.MSG_TYPE_DETACH);
      types.add(PropertyMessage.MSG_TYPE_PROPERTY);
      types.add(ChatClient.MSG_TYPE_COM);
      types.add(SocialClient.MSG_TYPE_BLOCK_LIST);
      types.add(CombatClient.MSG_TYPE_DAMAGE);
      types.add(WorldManagerClient.MSG_TYPE_UPDATEWNODE);
      types.add(WorldManagerClient.MSG_TYPE_MOB_PATH);
      types.add(WorldManagerClient.MSG_TYPE_WNODECORRECT);
      types.add(WorldManagerClient.MSG_TYPE_ORIENT);
      types.add(WorldManagerClient.MSG_TYPE_SOUND);
      types.add(AnimationClient.MSG_TYPE_INVOKE_EFFECT);
      types.add(WorldManagerClient.MSG_TYPE_EXTENSION);
      types.add(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
      types.add(InventoryClient.MSG_TYPE_INV_UPDATE);
      types.add(CombatClient.MSG_TYPE_ABILITY_STATUS);
      types.add(CombatClient.MSG_TYPE_ABILITY_UPDATE);
      types.add(WorldManagerClient.MSG_TYPE_FOG);
      types.add(WorldManagerClient.MSG_TYPE_ROAD);
      types.add(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT);
      types.add(WorldManagerClient.MSG_TYPE_SET_AMBIENT);
      types.add(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY);
      types.add(WorldManagerClient.MSG_TYPE_FREE_OBJECT);
      types.add(MSG_TYPE_VOICE_PARMS);
      types.add(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
      types.add(MSG_TYPE_GET_MATCHING_PLAYERS);
      types.add(MSG_TYPE_ADD_STATIC_PERCEPTION);
      types.add(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
      if (this.extraPlayerMessageTypes != null)
        types.addAll(this.extraPlayerMessageTypes);
      this.perceptionFilter = new PerceptionFilter(types, true);
      PerceptionTrigger perceptionTrigger = new PerceptionTrigger();
      this.perceptionSubId = Engine.getAgent().createSubscription((IFilter)this.perceptionFilter, (MessageCallback)this.playerMessageCallback, 0, (MessageTrigger)perceptionTrigger);
      types.clear();
      types.add(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ);
      types.add(MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
      types.add(MSG_TYPE_GET_PLAYER_LOGIN_STATUS);
      types.add(MSG_TYPE_LOGOUT_PLAYER);
      this.responderFilter = new PerceptionFilter(types);
      this.responderSubId = Engine.getAgent().createSubscription((IFilter)this.responderFilter, (MessageCallback)this.playerMessageCallback, 8);
      this.responderFilter2 = new PerceptionFilter();
      this.responderSubId2 = Engine.getAgent().createSubscription((IFilter)this.responderFilter2, (MessageCallback)this, 8);
      types.clear();
      types.add(Management.MSG_TYPE_GET_PLUGIN_STATUS);
      Engine.getAgent().createSubscription((IFilter)new MessageTypeFilter(types), (MessageCallback)pluginMessageCallback, 8);
      MessageTypeFilter filter3 = new MessageTypeFilter();
      filter3.addType(MSG_TYPE_ACCOUNT_LOGIN);
      Engine.getAgent().createSubscription((IFilter)filter3, (MessageCallback)this);
      String log_rdp_counters = Engine.getProperty("atavism.log_rdp_counters");
      if (log_rdp_counters == null || log_rdp_counters.equals("false"))
        RDPServer.setCounterLogging(false);
      RDPServer.startRDPServer();
      initializeVoiceServerInformation();
      registerExtensionSubtype("voice_parms", MSG_TYPE_VOICE_PARMS);
      registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
      registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
      registerExtensionSubtype("ao.UPDATE_PLAYER_IGNORE_LIST", MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
      registerExtensionSubtype("ao.GET_MATCHING_PLAYERS", MSG_TYPE_GET_MATCHING_PLAYERS);
      registerExtensionSubtype("ao.PLAYER_IGNORE_LIST_REQ", MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
      Log.debug("ProxyPlugin before bindAddress");
      InetSocketAddress bindAddress = getBindAddress();
      Log.debug("ProxyPlugin after bindAddress " + bindAddress.getHostName() + " " + bindAddress.getAddress() + " " + bindAddress.getPort());
      Log.debug("ProxyPlugin before server socket");
      int port = Integer.parseInt(Engine.getProperty("atavism.proxy.bindport").trim());
      Log.debug("Proxy: getBindAddress port=" + port);
      String agent_name = Engine.getAgent().getName();
      String[] an = agent_name.split("_");
      int agentId = Integer.parseInt(an[1]);
      port += agentId - 1;
      int rdpChannels = Integer.parseInt(Engine.properties.getProperty("atavism.proxy.rdp_channels", String.valueOf(128)));
      for (int i = 0; i < rdpChannels; i++) {
        RDPServerSocket serverSocket = new RDPServerSocket();
        serverSocket.registerAcceptCallback(this);
        serverSocket.bind(Integer.valueOf(port), serverSocketReceiveBufferSize);
        if (Log.loggingDebug)
          Log.debug("BIND: binding for client tcp and rdp packets on port " + bindAddress.getPort() + " with rdpsocket: " + serverSocket.toString());
      }
      Log.debug("BIND: bound server socket");
      this.clientTCPMessageIO = ClientTCPMessageIO.setup(bindAddress, this, this);
      Log.debug("BIND: setup clientTCPMessage");
      this.clientTCPMessageIO.start("ClientIO");
      Log.debug("BIND: started clientTCPMessage");
      InetSocketAddress externalAddress = getExternalAddress(bindAddress);
      Log.debug("BIND: got external Address " + externalAddress.getHostName() + " " + externalAddress.getAddress() + " " + externalAddress.getPort());
      setPluginInfo("host=" + Engine.getProperty("atavism.proxy.externaladdress") + ",port=" + externalAddress.getPort());
      Log.debug("Registering proxy plugin");
      Engine.registerStatusReportingPlugin(this);
      Log.debug("Proxy: activation done");
      runCheck();
      Gauge.builder("event_qq_size", (Supplier)new Object(this)).register(Prometheus.registry());
      Gauge.builder("message_qq_size", (Supplier)new Object(this)).register(Prometheus.registry());
      Gauge.builder("message_qq_unqueued_size", (Supplier)new Object(this)).register(Prometheus.registry());
    } catch (Exception e) {
      throw new AORuntimeException("activate failed", e);
    }
  }
 
  private InetSocketAddress getBindAddress() throws IOException {
    int port;
    String propStr = Engine.getProperty("atavism.proxy.bindport");
    Log.debug("Proxy: getBindAddress propStr=" + propStr);
    if (propStr != null) {
      port = Integer.parseInt(propStr.trim());
      Log.debug("Proxy: getBindAddress port=" + port);
      String agent_name = Engine.getAgent().getName();
      String[] an = agent_name.split("_");
      int agentId = Integer.parseInt(an[1]);
      port += agentId - 1;
      Log.debug("Proxy: getBindAddress port=" + port);
    } else {
      port = Integer.parseInt(Engine.getProperty("atavism.proxyport").trim());
    }
    Log.debug("Proxy: getBindAddress port=" + port);
    propStr = Engine.getProperty("atavism.proxy.bindaddress");
    Log.debug("Proxy: getBindAddress propStr=" + propStr + " " + Character.digit(propStr.charAt(0), 16) + " " + Character.digit(propStr.charAt(1), 16) + " " + Character.digit(propStr.charAt(2), 16) + " c=");
    int count = 0;
    if (propStr.contains("."))
      for (int i = 0; i < propStr.length(); i++) {
        if (propStr.charAt(i) == '.')
          count++;
      }
    InetAddress address = null;
    InetAddress[] address2 = null;
    if (count != 3 || Character.digit(propStr.charAt(0), 10) != -1);
    if (propStr != null)
      try {
        address = InetAddress.getByName(propStr.trim());
        address2 = InetAddress.getAllByName(propStr.trim());
        for (InetAddress ai : address2)
          Log.debug("Proxy: getBindAddress address2=" + ai + " " + ai.getHostName() + " " + ai.getHostAddress());
        Log.debug("Proxy: getBindAddress address=" + address + " " + address.getHostName() + " " + address.getHostAddress());
      } catch (UnknownHostException e) {
        log.error("getBindAddress " + e.getMessage() + " " + e.getLocalizedMessage());
      }
    Log.debug("Proxy: getBindAddress address=" + address + " " + address.getHostName() + " " + address.getAddress());
    return new InetSocketAddress(address, port);
  }
 
  private InetSocketAddress getExternalAddress(InetSocketAddress bindAddress) throws IOException {
    int port;
    InetAddress address;
    String propStr = Engine.getProperty("atavism.proxy.externalport");
    Log.debug("Proxy: getExternalAddress ext port propStr=" + propStr);
    if (propStr != null) {
      port = Integer.parseInt(propStr.trim());
    } else {
      port = bindAddress.getPort();
    }
    Log.debug("Proxy: getExternalAddress port=" + port);
    propStr = Engine.getProperty("atavism.proxy.externaladdress");
    Log.debug("Proxy: getExternalAddress ext addr propStr=" + propStr);
    if (propStr != null) {
      address = InetAddress.getByName(propStr.trim());
    } else {
      address = bindAddress.getAddress();
      Log.debug("Proxy: getExternalAddress else address=" + address);
      if (address.isAnyLocalAddress()) {
        address = InetAddress.getLocalHost();
        Log.debug("Proxy: getExternalAddress get local host address=" + address + " " + address.getHostName() + " " + address.getHostAddress());
      }
    }
    Log.debug("Proxy: getExternalAddress address=" + address + " " + address.getHostName() + " " + address.getAddress());
    return new InetSocketAddress(address, port);
  }
 
  private String howla() {
    String characters = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnoprstquwxyz123456789";
    String k = "";
    for (int i = 0; i < 14; i++) {
      Random random = new Random();
      k = k + characters.charAt(random.nextInt(characters.length() - 1));
    }
    return k;
  }
 
  private void runCheck() {
    String email = Engine.getProperty("atavism.licence.email");
    String licencekey = Engine.getProperty("atavism.licence.key");
    String proxy_id = Engine.getProperty("atavism.proxy.id");
    int num = 0;
    int proxyId = 0;
    try {
      if (proxy_id != null && proxy_id != "")
        proxyId = Integer.parseInt(proxy_id);
    } catch (NumberFormatException numberFormatException) {}
    String[] url = { "https://apanel.atavismonline.com/login/verifyserver.php", "https://licensing2.dragonsan.com:2443/login/verifyserver.php", "https://licensing1.atavismonline.com/login/verifyserver.php", "https://licensing.dragonsan.com/login/verifyserver.php", "https://licensing1.dragonsan.com/login/verifyserver.php", "https://licensing.atavismonline.com/login/verifyserver.php", "https://licensing2.atavismonline.com/login/verifyserver.php" };
    String resSor = howla();
    rck reCheck = new rck(this, resSor);
    Engine.getExecutor().scheduleAtFixedRate((Runnable)reCheck, 300L, 300L, TimeUnit.SECONDS);
    while (num < url.length) {
      boolean failed = false;
      try {
        String res = "";
        URL urlObj = new URL(url[num]);
        URLConnection lu = urlObj.openConnection();
        lu.setConnectTimeout(10000);
        String data = "email=" + URLEncoder.encode(email, "UTF-8") + "&licence=" + URLEncoder.encode(licencekey, "UTF-8") + "&ver=" + URLEncoder.encode("10.7.0", "UTF-8") + "&addr=" + URLEncoder.encode(Engine.getProperty("atavism.proxy.bindaddress"), "UTF-8") + "&sor=" + URLEncoder.encode(resSor, "UTF-8") + "&c=" + URLEncoder.encode("0", "UTF-8") + "&cp=" + this.playerManager.getPlayerCount() + " &pi=" + proxyId + "&build=" + URLEncoder.encode(ServerVersion.getBuildDate(), "UTF-8") + "&m=" + MaxConcurrentUsers;
        lu.setDoOutput(true);
        OutputStreamWriter wr = new OutputStreamWriter(lu.getOutputStream());
        wr.write(data);
        wr.flush();
        BufferedReader rd = new BufferedReader(new InputStreamReader(lu.getInputStream()));
        String line = "";
        while ((line = rd.readLine()) != null)
          res = res + line;
        wr.flush();
        wr.close();
        if (debugLic)
          System.out.println("\n" + url[num] + "\n" + res + "\n");
        res = HelperFunctions.readEncodedString(Base64.decode(res));
        String[] output = res.split(":");
        if (debugLic)
          System.out.println("\nsec: " + resSor + "\n s: " + HelperFunctions.readEncodedString(Base64.decode(output[2])) + "\n");
        if (EncryptionHelper.passwordMD5Check(output[0], getTemp()) && resSor.equals(HelperFunctions.readEncodedString(Base64.decode(output[2])))) {
          this.connectionLimit = Integer.parseInt(HelperFunctions.readEncodedString(Base64.decode(output[1])));
        } else {
          System.out.println("\nLicense verification failed");
          Log.error("License verification failed");
        }
        Log.debug("CONNECTOR: connections set to: " + this.connectionLimit);
      } catch (Exception e) {
        Log.error("CONNECTOR: failed verifying " + e);
        if (debugLic)
          System.out.println("\n" + url[num] + "\n" + e);
        num++;
        failed = true;
      }
      if (!failed)
        return;
    }
    System.out.println("\nLicense verification failed");
    Log.error("License verification failed");
    this.connectionLimit = 0;
  }
 
  public static boolean debugLic = false;
 
  protected Lock commandMapLock;
 
  Map<String, RegisteredCommand> commandMap;
 
  CommandAccessCheck defaultCommandAccess;
 
  SquareQueue<Player, Message> messageQQ;
 
  SQThreadPool messageThreadPool;
 
  private final SquareQueue<Player, Event> eventQQ;
 
  private SQThreadPool<Player, Event> eventThreadPool;
 
  private final SquareQueue<Player, Event> slowEventQQ;
 
  private SQThreadPool<Player, Event> slowEventThreadPool;
 
  AOMeter clientMsgMeter;
 
  protected ConcurrentHashMap<OID, Long> playerLastClientTime;
 
  protected ConcurrentHashMap<OID, Long> playerLastServerTime;
 
  protected ConcurrentHashMap<OID, Long> playerFirstSpeedHackTime;
 
  protected ConcurrentHashMap<OID, Long> playerSpeedHackCount;
 
  public boolean defaultAllowClientToClientMessage;
 
  protected HashMap<String, MessageType> extensionMessageRegistry;
 
  private final ExecutorService logoutExecutor;
 
  protected AccountDatabase aDB;
 
  protected PerceptionFilter perceptionFilter;
 
  protected long perceptionSubId;
 
  protected PerceptionFilter responderFilter;
 
  protected PerceptionFilter responderFilter2;
 
  protected long responderSubId;
 
  protected long responderSubId2;
 
  protected int clientPort;
 
  public Map<String, String> getStatusMap() {
    Map<String, String> status = new HashMap<>();
    status.put("players", Integer.toString(this.playerManager.getPlayerCount()));
    return status;
  }
 
  public void registerCommand(String command, CommandParser parser) {
    this.commandMapLock.lock();
    try {
      this.commandMap.put(command, new RegisteredCommand(parser, this.defaultCommandAccess));
    } finally {
      this.commandMapLock.unlock();
    }
  }
 
  public void registerCommand(String command, CommandParser parser, CommandAccessCheck access) {
    this.commandMapLock.lock();
    try {
      this.commandMap.put(command, new RegisteredCommand(parser, access));
    } finally {
      this.commandMapLock.unlock();
    }
  }
 
  void registerHooks() {
    log.debug("registering hooks");
    getHookManager().addHook(SocialClient.MSG_TYPE_BLOCK_LIST, (Hook)new BlockListHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT, (Hook)new DisplayContextHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_DETACH, (Hook)new DetachHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_ANIMATION, (Hook)new AnimationHook(this));
    getHookManager().addHook(AnimationClient.MSG_TYPE_INVOKE_EFFECT, (Hook)new InvokeEffectHook(this));
    getHookManager().addHook(PropertyMessage.MSG_TYPE_PROPERTY, (Hook)new PropertyHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_EXTENSION, (Hook)new ExtensionHook(this));
    getHookManager().addHook(CombatClient.MSG_TYPE_ABILITY_STATUS, (Hook)new AbilityStatusHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY, (Hook)new TargetedPropertyHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO, (Hook)new PerceptionHook(this));
    getHookManager().addHook(ChatClient.MSG_TYPE_COM, (Hook)new ComHook(this));
    getHookManager().addHook(CombatClient.MSG_TYPE_DAMAGE, (Hook)new DamageHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_SYS_CHAT, (Hook)new SysChatHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_UPDATEWNODE, (Hook)new UpdateWNodeHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_MOB_PATH, (Hook)new UpdateMobPathHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_WNODECORRECT, (Hook)new WNodeCorrectHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_ORIENT, (Hook)new OrientHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_SOUND, (Hook)new SoundHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_FOG, (Hook)new FogHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_ROAD, (Hook)new RoadHook(this));
    getHookManager().addHook(InventoryClient.MSG_TYPE_INV_UPDATE, (Hook)new InvUpdateHook(this));
    getHookManager().addHook(CombatClient.MSG_TYPE_ABILITY_UPDATE, (Hook)new AbilityUpdateHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT, (Hook)new NewDirLightHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_FREE_OBJECT, (Hook)new FreeObjectHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_SET_AMBIENT, (Hook)new SetAmbientHook(this));
    getHookManager().addHook(WorldManagerClient.MSG_TYPE_P2P_EXTENSION, (Hook)new P2PExtensionHook(this));
    getHookManager().addHook(MSG_TYPE_VOICE_PARMS, (Hook)new VoiceParmsHook(this));
    getHookManager().addHook(MSG_TYPE_PLAYER_PATH_REQ, (Hook)new PlayerPathReqHook(this));
    getHookManager().addHook(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ, (Hook)new InstanceEntryReqHook(this));
    getHookManager().addHook(Management.MSG_TYPE_GET_PLUGIN_STATUS, (Hook)new GetPluginStatusHook(this));
    getHookManager().addHook(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST, (Hook)new UpdatePlayerIgnoreListHook(this));
    getHookManager().addHook(MSG_TYPE_GET_MATCHING_PLAYERS, (Hook)new GetMatchingPlayersHook(this));
    getHookManager().addHook(MSG_TYPE_PLAYER_IGNORE_LIST_REQ, (Hook)new PlayerIgnoreListReqHook(this));
    getHookManager().addHook(MSG_TYPE_GET_PLAYER_LOGIN_STATUS, (Hook)new GetPlayerLoginStatusHook(this, null));
    getHookManager().addHook(MSG_TYPE_LOGOUT_PLAYER, (Hook)new LogoutPlayerHook(this, null));
    getHookManager().addHook(MSG_TYPE_ADD_STATIC_PERCEPTION, (Hook)new AddStaticPerceptionHook(this, null));
    getHookManager().addHook(MSG_TYPE_REMOVE_STATIC_PERCEPTION, (Hook)new RemoveStaticPerceptionHook(this, null));
    getHookManager().addHook(MSG_TYPE_ACCOUNT_LOGIN, (Hook)new AccountLoginHook(this, null));
  }
 
  void callEngineOnMessage(Message message, int flags) {
    handleMessage(message, flags);
  }
 
  protected void initializeVoiceServerInformation() {
    voiceServerHost = Engine.properties.getProperty("atavism.voiceserver");
    String s = Engine.properties.getProperty("atavism.voiceport");
    if (s != null)
      voiceServerPort = Integer.valueOf(Integer.parseInt(s));
    if (Log.loggingDebug)
      log.debug("initializeVoiceServerInformation: voiceServerHost " + voiceServerHost + ", voiceServerPort " + voiceServerPort);
  }
 
  public void acceptConnection(ClientConnection con) {
    Log.info("ProxyPlugin: CONNECTION remote=" + con);
    con.registerMessageCallback(this);
  }
 
  public void processPacket(ClientConnection con, AOByteBuffer buf) {
    try {
      long time1 = System.nanoTime();
      if (Log.loggingNet)
        if (ClientConnection.getLogMessageContents()) {
          Log.net("ProxyPlugin.processPacket: con " + con + ", length " + buf.limit() + ", packet " + DebugUtils.byteArrayToHexString(buf));
        } else {
          Log.net("ProxyPlugin.processPacket: con " + con + ", buf " + buf);
        }
      Event event = Engine.getEventServer().parseBytes(buf, con);
      if (event == null) {
        Log.error("Engine: could not parse packet data, remote=" + con);
        return;
      }
      SquareQueue<Player, Event> qq = this.eventQQ;
      if (event instanceof AuthorizedLoginEvent)
        qq = this.slowEventQQ;
      Player player = (Player)con.getAssociation();
      if (player == null)
        if (event instanceof AuthorizedLoginEvent) {
          Log.info("ProxyPlugin: LOGIN_RECV remote=" + con + " playerOid=" + ((AuthorizedLoginEvent)event).getOid());
          player = new Player(((AuthorizedLoginEvent)event).getOid(), con);
        } else {
          Log.error("Cannot process event for connection with no player: " + con);
          return;
        }
      this.playerManager.processEvent(player, event, qq);
      long time2 = System.nanoTime();
      Timer.builder("process_packet_time").tags(new String[] { "event", event.getClass().getSimpleName() }).publishPercentiles(new double[] { 0.9D }).register(Prometheus.registry()).record(Duration.ofNanos(time2 - time1));
    } catch (AORuntimeException e) {
      Log.exception("ProxyPlugin.processPacket caught exception", (Exception)e);
    }
  }
 
  public Set<OID> getPlayerOids() {
    List<Player> players = new ArrayList<>(this.playerManager.getPlayerCount());
    this.playerManager.getPlayers(players);
    Set<OID> result = new HashSet<>(players.size());
    for (Player player : players)
      result.add(player.getOid());
    return result;
  }
 
  public List<String> getPlayerNames() {
    List<Player> players = new ArrayList<>(this.playerManager.getPlayerCount());
    Log.debug("ProxyPlugin.getPlayerNames: count is " + this.playerManager.getPlayerCount());
    this.playerManager.getPlayers(players);
    List<String> result = new ArrayList<>(players.size());
    for (Player player : players)
      result.add(player.getName() + " " + player.getOid() + " " + getName());
    Collections.sort(result);
    return result;
  }
 
  public List<String> getAllPlayerNames() {
    Log.debug("ProxyPlugin.getAllPlayerNames: count is " + this.playersOnlineList.size());
    List<String> result = new ArrayList<>(this.playersOnlineList.size());
    HashMap<OID, String> plays = new HashMap<>();
    plays.putAll(this.playersOnlineList);
    for (OID player : plays.keySet())
      result.add((String)plays.get(player) + " " + player + " " + (String)this.playersOnlineOnProxy.get(player));
    Collections.sort(result);
    return result;
  }
 
  public List<Player> getPlayers() {
    List<Player> players = new ArrayList<>(this.playerManager.getPlayerCount());
    this.playerManager.getPlayers(players);
    return players;
  }
 
  public Player getPlayer(OID oid) {
    return this.playerManager.getPlayer(oid);
  }
 
  public void addPlayerMessage(Message message, Player player) {
    long start = System.nanoTime();
    message.setEnqueueTime();
    this.messageQQ.insert(player, message);
    long microseconds = System.nanoTime() - start;
  }
 
  public void addFilteredProperty(String filteredProperty) {
    this.filteredProps.add(filteredProperty);
    this.cachedPlayerSpecificFilterProps.add(filteredProperty);
  }
 
  public void addPlayerSpecificProperty(String filteredProperty) {
    this.playerSpecificProps.add(filteredProperty);
    this.cachedPlayerSpecificFilterProps.add(filteredProperty);
  }
 
  protected void recreatePlayerSpecificCache() {
    this.cachedPlayerSpecificFilterProps = new HashSet<>();
    this.cachedPlayerSpecificFilterProps.addAll(this.filteredProps);
    this.cachedPlayerSpecificFilterProps.addAll(this.playerSpecificProps);
  }
 
  protected boolean processLogin(ClientConnection con, AuthorizedLoginEvent loginEvent) {
    Prometheus.registry().counter("player_login_request", new String[0]).increment();
    OID playerOid = loginEvent.getOid();
    String version = loginEvent.getVersion();
    int nPlayers = this.playerManager.getPlayerCount();
    String[] clientVersionCapabilities = null;
    if (version != null && version.length() > 0)
      clientVersionCapabilities = version.split(",");
    LinkedList<String> clientCapabilities = new LinkedList<>();
    String clientVersion = "";
    if (clientVersionCapabilities != null && clientVersionCapabilities.length > 0) {
      clientVersion = clientVersionCapabilities[0];
      for (int i = 1; i < clientVersionCapabilities.length; i++)
        clientCapabilities.add(clientVersionCapabilities[i].trim());
    }
    int versionCompare = ServerVersion.compareVersionStrings(clientVersion, "10.7.0");
    if (versionCompare != 0) {
      Log.warn("processLogin: unsupported version " + clientVersion + " from player: " + playerOid);
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Unsupported client version", this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "unsupported_version" }).increment();
      return false;
    }
    if (!isAdmin(playerOid) || nPlayers >= this.connectionLimit) {
      Log.debug("processLogin: player is not admin");
      if (nPlayers >= MaxConcurrentUsers || nPlayers >= this.connectionLimit) {
        Log.warn("processLogin: too many users, failed for player: " + playerOid);
        AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, this.capacityError, this.serverVersion);
        con.send(authorizedLoginResponseEvent.toBytes());
        Prometheus.registry().counter("player_login_result", new String[] { "status", "too_many_users_" + String.valueOf(this.connectionLimit) }).increment();
        return false;
      }
    } else {
      Log.debug("processLogin: player is admin, bypassing max check");
    }
    SecureToken token = SecureTokenManager.getInstance().importToken(loginEvent.getWorldToken());
    boolean validToken = true;
    if (!token.getValid()) {
      Log.debug("token is not valid");
      validToken = false;
    }
    OID characterOid = (OID)token.getProperty("character_oid");
    if (Log.loggingDebug)
      Log.debug("PlayerOID: " + playerOid);
    if (Log.loggingDebug)
      Log.debug("CharacterOID: " + characterOid);
    if (!playerOid.equals(characterOid)) {
      Log.debug("playerOid does not match character_oid");
      validToken = false;
    }
    if (!token.getProperty("proxy_server").equals(Engine.getAgent().getName())) {
      Log.debug("proxy_server does not match engine agent name");
      validToken = false;
    }
    if (!validToken) {
      Log.error("processLogin: invalid proxy token");
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, this.tokenError, this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "invalid_token" }).increment();
      return false;
    }
    try {
      TargetMessage getPlayerLoginStatus = new TargetMessage(MSG_TYPE_GET_PLAYER_LOGIN_STATUS, playerOid);
      PlayerLoginStatus loginStatus = (PlayerLoginStatus)Engine.getAgent().sendRPCReturnObject((Message)getPlayerLoginStatus);
      if (this.proxyLoginCallback.duplicateLogin(loginStatus, con)) {
        if (loginStatus != null) {
          if (Log.loggingInfo)
            Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " name=" + loginStatus.name + " existingCon=" + loginStatus.clientCon + " existingProxy=" + loginStatus.proxyPluginName);
        } else if (Log.loggingInfo) {
          Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " loginStatus is null");
        }
        log.debug("processLogin: Send logout");
        Prometheus.registry().counter("player_logout", new String[] { "reason", "duplicate" }).increment();
        TargetMessage logoutPly = new TargetMessage(MSG_TYPE_LOGOUT_PLAYER, playerOid);
        Engine.getAgent().sendRPCReturnObject((Message)logoutPly);
        log.debug("processLogin: Send logout | ");
        AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Already connected", this.serverVersion);
        con.send(authorizedLoginResponseEvent.toBytes());
        Prometheus.registry().counter("player_login_result", new String[] { "status", "duplicate" }).increment();
        return false;
      }
    } catch (NoRecipientsException e) {
      if (Log.loggingDebug)
        log.debug("processLogin: OK! player is not logged " + e);
    }
    Player player = new Player(playerOid, con);
    player.setStatus(1);
    if (!this.playerManager.addPlayer(player)) {
      player = this.playerManager.getPlayer(playerOid);
      Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " existing=" + player.getConnection());
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Already connected", this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "duplicate_add" }).increment();
      return false;
    }
    con.setAssociation(player);
    player.setVersion(clientVersion);
    player.setCapabilities(clientCapabilities);
    String errorMessage = this.proxyLoginCallback.preLoad(player, con);
    if (errorMessage != null) {
      this.playerManager.removePlayer(playerOid);
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, errorMessage, this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "pre_load_error" }).increment();
      return false;
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: loading object: " + playerOid + ", con=" + con);
    if (!loadPlayerObject(player)) {
      Log.error("processLogin: could not load object " + playerOid);
      this.playerManager.removePlayer(playerOid);
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed", this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "not_loaded" }).increment();
      return false;
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: loaded player object: " + playerOid);
    errorMessage = this.proxyLoginCallback.postLoad(player, con);
    if (errorMessage != null) {
      this.playerManager.removePlayer(playerOid);
      AuthorizedLoginResponseEvent authorizedLoginResponseEvent = new AuthorizedLoginResponseEvent(playerOid, false, errorMessage, this.serverVersion);
      con.send(authorizedLoginResponseEvent.toBytes());
      Prometheus.registry().counter("player_login_result", new String[] { "status", "error" }).increment();
      return false;
    }
    AuthorizedLoginResponseEvent loginResponse = new AuthorizedLoginResponseEvent(playerOid, true, "Login Succeeded", this.serverVersion + ", " + this.serverCapabilitiesSentToClient);
    con.send(loginResponse.toBytes());
    if (Log.loggingDebug)
      Log.debug("Login response sent for playerOid=" + playerOid + " the authorized login response message is : " + loginResponse.getMessage());
    this.playerManager.addStaticPerception(player, playerOid);
    boolean loginOK = processLoginHelper(con, player);
    if (Log.loggingDebug)
      log.debug("processLogin: loginOK?:" + loginOK + "  | player=" + player);
    if (!loginOK) {
      if (Log.loggingDebug)
        Log.debug("processLogin: loading object: " + playerOid + ", con=" + con + " login failed disconect player");
      con.setAssociation(null);
      if (this.perceptionFilter.removeTarget(playerOid)) {
        FilterUpdate filterUpdate = new FilterUpdate(1);
        filterUpdate.removeFieldValue(1, playerOid);
        Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
        this.responderFilter.removeTarget(playerOid);
        this.responderFilter2.removeTarget(playerOid);
        Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
        Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
      }
      this.playerManager.removeStaticPerception(player, playerOid);
      this.playerManager.removePlayer(playerOid);
      Prometheus.registry().counter("rdp_connection_closed", new String[] { "reason", "bad_login" }).increment();
      con.close();
    } else {
      this.proxyLoginCallback.postSpawn(player, con);
      this.playerManager.loginComplete(player, this.eventQQ);
      SubjectMessage loginSpawned = new SubjectMessage(MSG_TYPE_LOGIN_SPAWNED);
      loginSpawned.setSubject(playerOid);
      Engine.getAgent().sendBroadcast((Message)loginSpawned);
      processPlayerIgnoreList(player);
      OID accountID = (OID)EnginePlugin.getObjectProperty(playerOid, WorldManagerClient.NAMESPACE, "accountId");
      this.clientConnections.put(accountID, con);
      if (player.getStatus() == 3) {
        ConnectionResetMessage message = new ConnectionResetMessage(this, con, player);
        message.setEnqueueTime();
        this.messageQQ.insert(player, message);
      }
    }
    Prometheus.registry().counter("player_login_result", new String[] { "status", loginOK ? "ok" : "failed" }).increment();
    if (Log.loggingDebug) {
      log.debug("processLogin: loginOK?:" + loginOK + " || player=" + player);
      log.debug("processLogin: loginOK:" + loginOK + " end");
    }
    return loginOK;
  }
 
  protected boolean loadPlayerObject(Player player) {
    // Byte code:
    //   0: getstatic atavism/server/util/Log.loggingDebug : Z
    //   3: ifeq -> 32
    //   6: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   9: new java/lang/StringBuilder
    //   12: dup
    //   13: invokespecial <init> : ()V
    //   16: ldc_w 'loadPlayerObject player '
    //   19: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   22: aload_1
    //   23: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   26: invokevirtual toString : ()Ljava/lang/String;
    //   29: invokevirtual debug : (Ljava/lang/String;)V
    //   32: aconst_null
    //   33: astore_2
    //   34: aconst_null
    //   35: astore_3
    //   36: iconst_1
    //   37: istore #4
    //   39: aload_1
    //   40: invokevirtual getOid : ()Latavism/server/engine/OID;
    //   43: astore #5
    //   45: new java/util/ArrayList
    //   48: dup
    //   49: invokespecial <init> : ()V
    //   52: astore #6
    //   54: aload #5
    //   56: aload #6
    //   58: invokestatic loadSubObject : (Latavism/server/engine/OID;Ljava/util/Collection;)Latavism/server/engine/OID;
    //   61: astore #7
    //   63: getstatic atavism/server/util/Log.loggingDebug : Z
    //   66: ifeq -> 106
    //   69: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   72: new java/lang/StringBuilder
    //   75: dup
    //   76: invokespecial <init> : ()V
    //   79: ldc_w 'loadPlayerObject player '
    //   82: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   85: aload_1
    //   86: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   89: ldc_w ' oidResult='
    //   92: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   95: aload #7
    //   97: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   100: invokevirtual toString : ()Ljava/lang/String;
    //   103: invokevirtual debug : (Ljava/lang/String;)V
    //   106: aload #7
    //   108: ifnonnull -> 113
    //   111: iconst_0
    //   112: ireturn
    //   113: new atavism/server/math/Point
    //   116: dup
    //   117: invokespecial <init> : ()V
    //   120: astore #8
    //   122: invokestatic getDatabase : ()Latavism/server/engine/Database;
    //   125: aload #5
    //   127: getstatic atavism/server/plugins/WorldManagerClient.NAMESPACE : Latavism/server/engine/Namespace;
    //   130: aload #8
    //   132: invokevirtual getLocation : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Latavism/server/math/Point;)Latavism/server/engine/OID;
    //   135: astore #9
    //   137: getstatic atavism/server/util/Log.loggingDebug : Z
    //   140: ifeq -> 189
    //   143: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   146: new java/lang/StringBuilder
    //   149: dup
    //   150: invokespecial <init> : ()V
    //   153: ldc_w 'loadPlayerObject instanceOid '
    //   156: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   159: aload #9
    //   161: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   164: ldc_w ' instanceEntryAllowed:'
    //   167: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   170: aload_0
    //   171: aload #5
    //   173: aload #9
    //   175: aload #8
    //   177: invokespecial instanceEntryAllowed : (Latavism/server/engine/OID;Latavism/server/engine/OID;Latavism/server/math/Point;)Z
    //   180: invokevirtual append : (Z)Ljava/lang/StringBuilder;
    //   183: invokevirtual toString : ()Ljava/lang/String;
    //   186: invokevirtual debug : (Ljava/lang/String;)V
    //   189: getstatic atavism/server/util/Log.loggingDebug : Z
    //   192: ifeq -> 222
    //   195: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   198: new java/lang/StringBuilder
    //   201: dup
    //   202: invokespecial <init> : ()V
    //   205: ldc_w 'loadPlayerObject: trying to load player into instance: '
    //   208: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   211: aload #9
    //   213: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   216: invokevirtual toString : ()Ljava/lang/String;
    //   219: invokevirtual debug : (Ljava/lang/String;)V
    //   222: aload_0
    //   223: getfield aDB : Latavism/agis/database/AccountDatabase;
    //   226: aload #5
    //   228: invokevirtual GetGuildId : (Latavism/server/engine/OID;)I
    //   231: istore #10
    //   233: getstatic atavism/server/util/Log.loggingDebug : Z
    //   236: ifeq -> 266
    //   239: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   242: new java/lang/StringBuilder
    //   245: dup
    //   246: invokespecial <init> : ()V
    //   249: ldc_w 'loadPlayerObject: load player guildID: '
    //   252: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   255: iload #10
    //   257: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   260: invokevirtual toString : ()Ljava/lang/String;
    //   263: invokevirtual debug : (Ljava/lang/String;)V
    //   266: aconst_null
    //   267: astore #11
    //   269: aload_0
    //   270: aload #5
    //   272: aload #9
    //   274: aload #8
    //   276: invokespecial instanceEntryAllowed : (Latavism/server/engine/OID;Latavism/server/engine/OID;Latavism/server/math/Point;)Z
    //   279: ifeq -> 471
    //   282: aload #9
    //   284: ldc_w -262145
    //   287: invokestatic getInstanceInfo : (Latavism/server/engine/OID;I)Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   290: astore #12
    //   292: getstatic atavism/server/util/Log.loggingDebug : Z
    //   295: ifeq -> 387
    //   298: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   301: new java/lang/StringBuilder
    //   304: dup
    //   305: invokespecial <init> : ()V
    //   308: ldc_w 'loadPlayerObject InstanceInfo '
    //   311: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   314: aload #12
    //   316: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   319: ldc_w ' plyOid='
    //   322: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   325: aload #12
    //   327: getfield playerOid : Latavism/server/engine/OID;
    //   330: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   333: ldc_w ' tempId'
    //   336: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   339: aload #12
    //   341: getfield templateID : I
    //   344: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   347: ldc_w ' groupId'
    //   350: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   353: aload #12
    //   355: getfield groupOid : Latavism/server/engine/OID;
    //   358: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   361: ldc_w ' guildId'
    //   364: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   367: aload #12
    //   369: getfield guildId : I
    //   372: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   375: ldc_w ' start do '
    //   378: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   381: invokevirtual toString : ()Ljava/lang/String;
    //   384: invokevirtual debug : (Ljava/lang/String;)V
    //   387: aload #12
    //   389: getfield oid : Latavism/server/engine/OID;
    //   392: ifnull -> 471
    //   395: aload #12
    //   397: getfield populationLimit : I
    //   400: iconst_1
    //   401: if_icmplt -> 417
    //   404: aload #12
    //   406: getfield playerPopulation : I
    //   409: aload #12
    //   411: getfield populationLimit : I
    //   414: if_icmpge -> 471
    //   417: aload #5
    //   419: invokestatic loadObject : (Latavism/server/engine/OID;)Latavism/server/engine/OID;
    //   422: astore #11
    //   424: getstatic atavism/server/util/Log.loggingDebug : Z
    //   427: ifeq -> 471
    //   430: new java/lang/StringBuilder
    //   433: dup
    //   434: invokespecial <init> : ()V
    //   437: ldc_w 'loadPlayerObject: loading player into instance: '
    //   440: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   443: aload #12
    //   445: getfield oid : Latavism/server/engine/OID;
    //   448: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   451: ldc_w ' of ID: '
    //   454: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   457: aload #12
    //   459: getfield templateID : I
    //   462: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   465: invokevirtual toString : ()Ljava/lang/String;
    //   468: invokestatic debug : (Ljava/lang/String;)V
    //   471: aload_3
    //   472: ifnull -> 494
    //   475: aload_2
    //   476: invokevirtual getFallbackFlag : ()Z
    //   479: ifne -> 494
    //   482: aload #5
    //   484: getstatic atavism/server/engine/Namespace.OBJECT_MANAGER : Latavism/server/engine/Namespace;
    //   487: ldc 'instanceStack'
    //   489: aload_3
    //   490: invokestatic setObjectProperty : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Ljava/lang/String;Ljava/io/Serializable;)Ljava/io/Serializable;
    //   493: pop
    //   494: aload #11
    //   496: ifnull -> 559
    //   499: aload_2
    //   500: ifnull -> 1461
    //   503: aload #5
    //   505: getstatic atavism/server/engine/Namespace.OBJECT_MANAGER : Latavism/server/engine/Namespace;
    //   508: ldc 'currentInstanceName'
    //   510: aload_2
    //   511: invokevirtual getInstanceID : ()I
    //   514: invokestatic valueOf : (I)Ljava/lang/Integer;
    //   517: invokestatic setObjectProperty : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Ljava/lang/String;Ljava/io/Serializable;)Ljava/io/Serializable;
    //   520: pop
    //   521: getstatic atavism/server/util/Log.loggingDebug : Z
    //   524: ifeq -> 1461
    //   527: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   530: new java/lang/StringBuilder
    //   533: dup
    //   534: invokespecial <init> : ()V
    //   537: ldc_w 'INSTANCE: setting current instance prop: '
    //   540: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   543: aload_2
    //   544: invokevirtual getInstanceID : ()I
    //   547: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   550: invokevirtual toString : ()Ljava/lang/String;
    //   553: invokevirtual debug : (Ljava/lang/String;)V
    //   556: goto -> 1461
    //   559: iload #4
    //   561: ifeq -> 1092
    //   564: aload #5
    //   566: getstatic atavism/server/engine/Namespace.OBJECT_MANAGER : Latavism/server/engine/Namespace;
    //   569: ldc 'currentInstanceName'
    //   571: invokestatic getObjectProperty : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Ljava/lang/String;)Ljava/io/Serializable;
    //   574: checkcast java/lang/Integer
    //   577: astore #12
    //   579: getstatic atavism/server/util/Log.loggingDebug : Z
    //   582: ifeq -> 612
    //   585: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   588: new java/lang/StringBuilder
    //   591: dup
    //   592: invokespecial <init> : ()V
    //   595: ldc_w 'Failed initial load, retrying with current instanceID='
    //   598: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   601: aload #12
    //   603: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   606: invokevirtual toString : ()Ljava/lang/String;
    //   609: invokevirtual debug : (Ljava/lang/String;)V
    //   612: getstatic atavism/server/util/Log.loggingDebug : Z
    //   615: ifeq -> 667
    //   618: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   621: new java/lang/StringBuilder
    //   624: dup
    //   625: invokespecial <init> : ()V
    //   628: ldc_w ' loadPlayerObject instanceID='
    //   631: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   634: aload #12
    //   636: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   639: ldc_w '  playerOid='
    //   642: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   645: aload #5
    //   647: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   650: ldc_w ' guildID='
    //   653: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   656: iload #10
    //   658: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   661: invokevirtual toString : ()Ljava/lang/String;
    //   664: invokevirtual debug : (Ljava/lang/String;)V
    //   667: aload #12
    //   669: invokevirtual intValue : ()I
    //   672: ifle -> 1092
    //   675: aload_0
    //   676: getfield instanceEntryCallback : Latavism/server/objects/InstanceEntryCallback;
    //   679: aload_1
    //   680: aload #12
    //   682: invokevirtual intValue : ()I
    //   685: aload #5
    //   687: iload #10
    //   689: invokeinterface selectInstance : (Latavism/server/objects/Player;ILatavism/server/engine/OID;I)Latavism/server/engine/OID;
    //   694: astore #9
    //   696: getstatic atavism/server/util/Log.loggingDebug : Z
    //   699: ifeq -> 729
    //   702: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   705: new java/lang/StringBuilder
    //   708: dup
    //   709: invokespecial <init> : ()V
    //   712: ldc_w 'loadPlayerObject instanceOid:'
    //   715: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   718: aload #9
    //   720: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   723: invokevirtual toString : ()Ljava/lang/String;
    //   726: invokevirtual debug : (Ljava/lang/String;)V
    //   729: aload #9
    //   731: ifnull -> 1092
    //   734: aload #9
    //   736: ldc_w -262145
    //   739: iconst_0
    //   740: invokestatic getInstanceInfo : (Latavism/server/engine/OID;IZ)Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   743: astore #13
    //   745: getstatic atavism/server/util/Log.loggingDebug : Z
    //   748: ifeq -> 834
    //   751: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   754: new java/lang/StringBuilder
    //   757: dup
    //   758: invokespecial <init> : ()V
    //   761: ldc_w ' loadPlayerObject InstanceInfo '
    //   764: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   767: aload #13
    //   769: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   772: ldc_w ' plyOid='
    //   775: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   778: aload #13
    //   780: getfield playerOid : Latavism/server/engine/OID;
    //   783: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   786: ldc_w ' tempId='
    //   789: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   792: aload #13
    //   794: getfield templateID : I
    //   797: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   800: ldc_w ' groupId='
    //   803: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   806: aload #13
    //   808: getfield groupOid : Latavism/server/engine/OID;
    //   811: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   814: ldc_w ' guildId='
    //   817: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   820: aload #13
    //   822: getfield guildId : I
    //   825: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   828: invokevirtual toString : ()Ljava/lang/String;
    //   831: invokevirtual debug : (Ljava/lang/String;)V
    //   834: aload #13
    //   836: getfield oid : Latavism/server/engine/OID;
    //   839: ifnull -> 1092
    //   842: aload #13
    //   844: getfield populationLimit : I
    //   847: ifle -> 1015
    //   850: aload #13
    //   852: getfield playerPopulation : I
    //   855: aload #13
    //   857: getfield populationLimit : I
    //   860: if_icmplt -> 1015
    //   863: getstatic atavism/server/util/Log.loggingDebug : Z
    //   866: ifeq -> 910
    //   869: new java/lang/StringBuilder
    //   872: dup
    //   873: invokespecial <init> : ()V
    //   876: ldc_w 'POP: got population: '
    //   879: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   882: aload #13
    //   884: getfield playerPopulation : I
    //   887: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   890: ldc_w ' and limit: '
    //   893: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   896: aload #13
    //   898: getfield populationLimit : I
    //   901: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   904: invokevirtual toString : ()Ljava/lang/String;
    //   907: invokestatic debug : (Ljava/lang/String;)V
    //   910: aload #13
    //   912: getfield templateID : I
    //   915: aload #13
    //   917: invokestatic handleFullInstance : (ILatavism/server/plugins/InstanceClient$InstanceInfo;)Latavism/server/engine/OID;
    //   920: astore #9
    //   922: aload #9
    //   924: ldc_w -262145
    //   927: invokestatic getInstanceInfo : (Latavism/server/engine/OID;I)Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   930: astore #13
    //   932: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   935: new java/lang/StringBuilder
    //   938: dup
    //   939: invokespecial <init> : ()V
    //   942: ldc_w ' loadPlayerObject 2 InstanceInfo '
    //   945: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   948: aload #13
    //   950: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   953: ldc_w ' plyOid'
    //   956: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   959: aload #13
    //   961: getfield playerOid : Latavism/server/engine/OID;
    //   964: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   967: ldc_w ' tempId='
    //   970: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   973: aload #13
    //   975: getfield templateID : I
    //   978: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   981: ldc_w ' groupId='
    //   984: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   987: aload #13
    //   989: getfield groupOid : Latavism/server/engine/OID;
    //   992: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   995: ldc_w ' guildId='
    //   998: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1001: aload #13
    //   1003: getfield guildId : I
    //   1006: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   1009: invokevirtual toString : ()Ljava/lang/String;
    //   1012: invokevirtual debug : (Ljava/lang/String;)V
    //   1015: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1018: ifeq -> 1062
    //   1021: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1024: new java/lang/StringBuilder
    //   1027: dup
    //   1028: invokespecial <init> : ()V
    //   1031: ldc_w 'Failed initial load, retrying with instanceOid='
    //   1034: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1037: aload #9
    //   1039: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1042: ldc_w ' and instanceName: '
    //   1045: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1048: aload #13
    //   1050: getfield name : Ljava/lang/String;
    //   1053: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1056: invokevirtual toString : ()Ljava/lang/String;
    //   1059: invokevirtual debug : (Ljava/lang/String;)V
    //   1062: new atavism/server/engine/BasicWorldNode
    //   1065: dup
    //   1066: invokespecial <init> : ()V
    //   1069: astore #14
    //   1071: aload #14
    //   1073: aload #9
    //   1075: invokevirtual setInstanceOid : (Latavism/server/engine/OID;)V
    //   1078: aload #5
    //   1080: aload #14
    //   1082: invokestatic fixWorldNode : (Latavism/server/engine/OID;Latavism/server/engine/BasicWorldNode;)Z
    //   1085: pop
    //   1086: iconst_0
    //   1087: istore #4
    //   1089: goto -> 266
    //   1092: aload_2
    //   1093: ifnull -> 1167
    //   1096: aload_2
    //   1097: invokevirtual getFallbackFlag : ()Z
    //   1100: ifeq -> 1167
    //   1103: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1106: ifeq -> 1165
    //   1109: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1112: new java/lang/StringBuilder
    //   1115: dup
    //   1116: invokespecial <init> : ()V
    //   1119: ldc_w 'loadPlayerObject instanceOid '
    //   1122: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1125: aload #9
    //   1127: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1130: ldc_w ' restorePoint:'
    //   1133: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1136: aload_2
    //   1137: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1140: ldc_w ' restorePoint.getFallbackFlag():'
    //   1143: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1146: aload_2
    //   1147: invokevirtual getFallbackFlag : ()Z
    //   1150: invokevirtual append : (Z)Ljava/lang/StringBuilder;
    //   1153: ldc_w ' return false'
    //   1156: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1159: invokevirtual toString : ()Ljava/lang/String;
    //   1162: invokevirtual debug : (Ljava/lang/String;)V
    //   1165: iconst_0
    //   1166: ireturn
    //   1167: aload #5
    //   1169: getstatic atavism/server/engine/Namespace.OBJECT_MANAGER : Latavism/server/engine/Namespace;
    //   1172: ldc 'instanceStack'
    //   1174: invokestatic getObjectProperty : (Latavism/server/engine/OID;Latavism/server/engine/Namespace;Ljava/lang/String;)Ljava/io/Serializable;
    //   1177: checkcast java/util/LinkedList
    //   1180: astore_3
    //   1181: aload_3
    //   1182: ifnull -> 1192
    //   1185: aload_3
    //   1186: invokevirtual size : ()I
    //   1189: ifne -> 1223
    //   1192: new java/lang/StringBuilder
    //   1195: dup
    //   1196: invokespecial <init> : ()V
    //   1199: ldc_w 'Failed finding matching instance, and restore stack is null or empty?'
    //   1202: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1205: aload_3
    //   1206: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1209: ldc_w ' return false'
    //   1212: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1215: invokevirtual toString : ()Ljava/lang/String;
    //   1218: invokestatic error : (Ljava/lang/String;)V
    //   1221: iconst_0
    //   1222: ireturn
    //   1223: aload_3
    //   1224: invokevirtual size : ()I
    //   1227: istore #12
    //   1229: aload_3
    //   1230: iload #12
    //   1232: iconst_1
    //   1233: isub
    //   1234: invokevirtual get : (I)Ljava/lang/Object;
    //   1237: checkcast atavism/server/objects/InstanceRestorePoint
    //   1240: astore_2
    //   1241: aload_2
    //   1242: invokevirtual getInstanceOid : ()Latavism/server/engine/OID;
    //   1245: astore #9
    //   1247: aload_2
    //   1248: invokevirtual getInstanceID : ()I
    //   1251: ifle -> 1313
    //   1254: aload_0
    //   1255: getfield instanceEntryCallback : Latavism/server/objects/InstanceEntryCallback;
    //   1258: aload_1
    //   1259: aload_2
    //   1260: invokevirtual getInstanceID : ()I
    //   1263: invokeinterface selectInstance : (Latavism/server/objects/Player;I)Latavism/server/engine/OID;
    //   1268: astore #9
    //   1270: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1273: ifeq -> 1313
    //   1276: new java/lang/StringBuilder
    //   1279: dup
    //   1280: invokespecial <init> : ()V
    //   1283: ldc_w 'Failed finding matching instance, retrying with restore point instanceID='
    //   1286: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1289: aload_2
    //   1290: invokevirtual getInstanceID : ()I
    //   1293: invokevirtual append : (I)Ljava/lang/StringBuilder;
    //   1296: ldc_w ' result: '
    //   1299: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1302: aload #9
    //   1304: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1307: invokevirtual toString : ()Ljava/lang/String;
    //   1310: invokestatic debug : (Ljava/lang/String;)V
    //   1313: aload #9
    //   1315: ifnull -> 1439
    //   1318: new atavism/server/engine/BasicWorldNode
    //   1321: dup
    //   1322: invokespecial <init> : ()V
    //   1325: astore #13
    //   1327: aload #13
    //   1329: aload #9
    //   1331: invokevirtual setInstanceOid : (Latavism/server/engine/OID;)V
    //   1334: aload #13
    //   1336: aload_2
    //   1337: invokevirtual getLoc : ()Latavism/server/math/Point;
    //   1340: invokevirtual setLoc : (Latavism/server/math/Point;)V
    //   1343: aload #13
    //   1345: aload_2
    //   1346: invokevirtual getOrientation : ()Latavism/server/math/Quaternion;
    //   1349: invokevirtual setOrientation : (Latavism/server/math/Quaternion;)V
    //   1352: aload #13
    //   1354: new atavism/server/math/AOVector
    //   1357: dup
    //   1358: fconst_0
    //   1359: fconst_0
    //   1360: fconst_0
    //   1361: invokespecial <init> : (FFF)V
    //   1364: invokevirtual setDir : (Latavism/server/math/AOVector;)V
    //   1367: aload #5
    //   1369: aload #13
    //   1371: invokestatic fixWorldNode : (Latavism/server/engine/OID;Latavism/server/engine/BasicWorldNode;)Z
    //   1374: istore #14
    //   1376: iload #14
    //   1378: ifne -> 1433
    //   1381: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1384: ifeq -> 1431
    //   1387: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1390: new java/lang/StringBuilder
    //   1393: dup
    //   1394: invokespecial <init> : ()V
    //   1397: ldc_w 'loadPlayerObject instanceOid '
    //   1400: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1403: aload #9
    //   1405: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1408: ldc_w ' rc:'
    //   1411: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1414: iload #14
    //   1416: invokevirtual append : (Z)Ljava/lang/StringBuilder;
    //   1419: ldc_w ' return false'
    //   1422: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1425: invokevirtual toString : ()Ljava/lang/String;
    //   1428: invokevirtual debug : (Ljava/lang/String;)V
    //   1431: iconst_0
    //   1432: ireturn
    //   1433: aload_2
    //   1434: invokevirtual getLoc : ()Latavism/server/math/Point;
    //   1437: astore #8
    //   1439: iconst_0
    //   1440: istore #4
    //   1442: aload_2
    //   1443: invokevirtual getFallbackFlag : ()Z
    //   1446: ifne -> 1458
    //   1449: aload_3
    //   1450: iload #12
    //   1452: iconst_1
    //   1453: isub
    //   1454: invokevirtual remove : (I)Ljava/lang/Object;
    //   1457: pop
    //   1458: goto -> 266
    //   1461: goto -> 1521
    //   1464: astore #11
    //   1466: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1469: new java/lang/StringBuilder
    //   1472: dup
    //   1473: invokespecial <init> : ()V
    //   1476: ldc_w 'loadPlayerObject instanceOid '
    //   1479: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1482: aload #9
    //   1484: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1487: ldc_w ' Exception: '
    //   1490: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1493: aload #11
    //   1495: invokevirtual getMessage : ()Ljava/lang/String;
    //   1498: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1501: ldc_w ' '
    //   1504: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1507: aload #11
    //   1509: invokevirtual getLocalizedMessage : ()Ljava/lang/String;
    //   1512: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1515: invokevirtual toString : ()Ljava/lang/String;
    //   1518: invokevirtual error : (Ljava/lang/String;)V
    //   1521: getstatic atavism/server/util/Log.loggingDebug : Z
    //   1524: ifeq -> 1560
    //   1527: getstatic atavism/server/plugins/ProxyPlugin.log : Latavism/server/util/Logger;
    //   1530: new java/lang/StringBuilder
    //   1533: dup
    //   1534: invokespecial <init> : ()V
    //   1537: ldc_w 'loadPlayerObject instanceOid '
    //   1540: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1543: aload #9
    //   1545: invokevirtual append : (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    //   1548: ldc_w ' END return true'
    //   1551: invokevirtual append : (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   1554: invokevirtual toString : ()Ljava/lang/String;
    //   1557: invokevirtual debug : (Ljava/lang/String;)V
    //   1560: iconst_1
    //   1561: ireturn
    // Line number table:
    //   Java source line number -> byte code offset
    //   #1848    -> 0
    //   #1849    -> 6
    //   #1850    -> 32
    //   #1851    -> 34
    //   #1852    -> 36
    //   #1853    -> 39
    //   #1856    -> 45
    //   #1857    -> 54
    //   #1858    -> 63
    //   #1859    -> 69
    //   #1860    -> 106
    //   #1861    -> 111
    //   #1864    -> 113
    //   #1865    -> 122
    //   #1866    -> 137
    //   #1867    -> 143
    //   #1869    -> 189
    //   #1870    -> 195
    //   #1872    -> 222
    //   #1873    -> 233
    //   #1874    -> 239
    //   #1877    -> 266
    //   #1878    -> 269
    //   #1879    -> 282
    //   #1880    -> 292
    //   #1881    -> 298
    //   #1884    -> 387
    //   #1887    -> 417
    //   #1888    -> 424
    //   #1889    -> 430
    //   #1894    -> 471
    //   #1895    -> 482
    //   #1898    -> 494
    //   #1899    -> 499
    //   #1900    -> 503
    //   #1901    -> 521
    //   #1902    -> 527
    //   #1909    -> 559
    //   #1911    -> 564
    //   #1912    -> 579
    //   #1913    -> 585
    //   #1914    -> 612
    //   #1915    -> 618
    //   #1917    -> 667
    //   #1928    -> 675
    //   #1929    -> 696
    //   #1930    -> 702
    //   #1931    -> 729
    //   #1933    -> 734
    //   #1934    -> 745
    //   #1935    -> 751
    //   #1936    -> 834
    //   #1937    -> 842
    //   #1938    -> 863
    //   #1939    -> 869
    //   #1940    -> 910
    //   #1941    -> 922
    //   #1942    -> 932
    //   #1944    -> 1015
    //   #1945    -> 1021
    //   #1946    -> 1062
    //   #1947    -> 1071
    //   #1948    -> 1078
    //   #1949    -> 1086
    //   #1950    -> 1089
    //   #1957    -> 1092
    //   #1958    -> 1103
    //   #1959    -> 1109
    //   #1961    -> 1165
    //   #1965    -> 1167
    //   #1967    -> 1181
    //   #1968    -> 1192
    //   #1969    -> 1221
    //   #1973    -> 1223
    //   #1974    -> 1229
    //   #1976    -> 1241
    //   #1978    -> 1247
    //   #1979    -> 1254
    //   #1980    -> 1270
    //   #1983    -> 1313
    //   #1984    -> 1318
    //   #1985    -> 1327
    //   #1987    -> 1334
    //   #1988    -> 1343
    //   #1989    -> 1352
    //   #1991    -> 1367
    //   #1993    -> 1376
    //   #1994    -> 1381
    //   #1995    -> 1387
    //   #1997    -> 1431
    //   #1999    -> 1433
    //   #2001    -> 1439
    //   #2003    -> 1442
    //   #2004    -> 1449
    //   #2007    -> 1458
    //   #2011    -> 1461
    //   #2008    -> 1464
    //   #2009    -> 1466
    //   #2012    -> 1521
    //   #2013    -> 1527
    //   #2015    -> 1560
    // Local variable table:
    //   start    length    slot    name    descriptor
    //   292    179    12    instanceInfo    Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   1071    21    14    wnode    Latavism/server/engine/BasicWorldNode;
    //   745    347    13    instanceInfo    Latavism/server/plugins/InstanceClient$InstanceInfo;
    //   579    513    12    instanceID    Ljava/lang/Integer;
    //   1327    112    13    wnode    Latavism/server/engine/BasicWorldNode;
    //   1376    63    14    rc    Z
    //   269    1189    11    result    Latavism/server/engine/OID;
    //   1229    229    12    size    I
    //   1466    55    11    e    Ljava/lang/Exception;
    //   0    1562    0    this    Latavism/server/plugins/ProxyPlugin;
    //   0    1562    1    player    Latavism/server/objects/Player;
    //   34    1528    2    restorePoint    Latavism/server/objects/InstanceRestorePoint;
    //   36    1526    3    restoreStack    Ljava/util/LinkedList;
    //   39    1523    4    first    Z
    //   45    1517    5    playerOid    Latavism/server/engine/OID;
    //   54    1508    6    namespaces    Ljava/util/List;
    //   63    1499    7    oidResult    Latavism/server/engine/OID;
    //   122    1440    8    location    Latavism/server/math/Point;
    //   137    1425    9    instanceOid    Latavism/server/engine/OID;
    //   233    1329    10    guildID    I
    // Local variable type table:
    //   start    length    slot    name    signature
    //   54    1508    6    namespaces    Ljava/util/List<Latavism/server/engine/Namespace;>;
    // Exception table:
    //   from    to    target    type
    //   266    1166    1464    java/lang/Exception
    //   1167    1222    1464    java/lang/Exception
    //   1223    1432    1464    java/lang/Exception
    //   1433    1461    1464    java/lang/Exception
  }
 
  protected boolean processLoginHelper(ClientConnection con, Player player) {
    OID playerOid = player.getOid();
    WorldManagerClient.ObjectInfo objInfo = WorldManagerClient.getObjectInfo(playerOid);
    if (objInfo == null) {
      Log.error("processLogin: Could not get player ObjectInfo oid=" + playerOid);
      return false;
    }
    if (Log.loggingDebug)
      log.debug("processLoginHelper objInfo " + objInfo.instanceOid);
    if (World.FollowsTerrainOverride != null) {
      Log.debug("using follows terrain override");
      objInfo.followsTerrain = World.FollowsTerrainOverride.booleanValue();
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: got object info: " + objInfo);
    player.setName(objInfo.name);
    InstanceClient.InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(objInfo.instanceOid, -262145);
    if (Log.loggingDebug)
      log.debug("InstanceInfo " + instanceInfo + " " + instanceInfo.playerOid + " " + instanceInfo.templateID + " " + instanceInfo.groupOid + " " + instanceInfo.guildId);
    if (instanceInfo == null) {
      Log.error("processLogin: unknown instanceOid=" + objInfo.instanceOid);
      return false;
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: sending template (scene) name: " + instanceInfo.templateName);
    WorldFileEvent worldFileEvent = new WorldFileEvent(instanceInfo.templateName);
    con.send(worldFileEvent.toBytes());
    player.sceneLoading(true);
    Log.debug("INFO: process login helper");
    con.send(objInfo.toBuffer(playerOid));
    DisplayContext dc = WorldManagerClient.getDisplayContext(playerOid);
    ModelInfoEvent modelInfoEvent = new ModelInfoEvent(playerOid);
    modelInfoEvent.setDisplayContext(dc);
    if (Log.loggingDebug)
      Log.debug("processLogin: got dc: " + dc);
    con.send(modelInfoEvent.toBytes());
    Map<String, DisplayContext> childMap = dc.getChildDCMap();
    if (childMap != null && !childMap.isEmpty()) {
      for (String slot : childMap.keySet()) {
        DisplayContext attachDC = childMap.get(slot);
        if (attachDC == null)
          throw new AORuntimeException("attach DC is null for obj: " + playerOid);
        OID attacheeOID = attachDC.getObjRef();
        if (attacheeOID == null)
          throw new AORuntimeException("attachee oid is null for obj: " + playerOid);
        if (Log.loggingDebug)
          Log.debug("processLogin: sending attach message to " + playerOid + " attaching to obj " + playerOid + ", object being attached=" + attacheeOID + " to slot " + slot + ", attachmentDC=" + attachDC);
        AttachEvent event = new AttachEvent(playerOid, attacheeOID, slot, attachDC);
        con.send(event.toBytes());
      }
      Log.debug("processLogin: done with processing attachments");
    }
    if (this.perceptionFilter.addTarget(playerOid)) {
      FilterUpdate filterUpdate = new FilterUpdate(1);
      filterUpdate.addFieldValue(1, playerOid);
      Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
      this.responderFilter.addTarget(playerOid);
      this.responderFilter2.addTarget(playerOid);
      Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
      Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
    }
    LoginMessage loginMessage = new LoginMessage(playerOid, objInfo.name);
    loginMessage.setInstanceOid(objInfo.instanceOid);
    loginMessage.setProxy(getName());
    AsyncRPCCallback asyncRPCCallback = new AsyncRPCCallback(player, "processLogin: got LoginMessage response");
    int expectedResponses = Engine.getAgent().sendBroadcastRPC((Message)loginMessage, (ResponseCallback)asyncRPCCallback);
    asyncRPCCallback.waitForResponses(expectedResponses);
    WorldManagerClient.updateObject(playerOid, playerOid);
    WorldManagerClient.TargetedExtensionMessage spawnBegin = new WorldManagerClient.TargetedExtensionMessage(playerOid, playerOid);
    spawnBegin.setExtensionType("ao.SCENE_BEGIN");
    spawnBegin.setProperty("action", "login");
    spawnBegin.setProperty("name", instanceInfo.name);
    spawnBegin.setProperty("templateName", instanceInfo.templateName);
    WorldManagerClient.TargetedExtensionMessage spawnEnd = new WorldManagerClient.TargetedExtensionMessage(playerOid, playerOid);
    spawnEnd.setExtensionType("ao.SCENE_END");
    spawnEnd.setProperty("action", "login");
    spawnEnd.setProperty("name", instanceInfo.name);
    spawnEnd.setProperty("templateName", instanceInfo.templateName);
    Integer perceptionCount = WorldManagerClient.spawn(playerOid, (Message)spawnBegin, (Message)spawnEnd);
    if (perceptionCount.intValue() < 0) {
      Log.error("processLogin: spawn failed error=" + perceptionCount + " playerOid=" + playerOid);
      if (perceptionCount.intValue() == -2)
        return false;
      return false;
    }
    if (perceptionCount.intValue() == 0 && player.supportsLoadingState()) {
      player.setLoadingState(1);
      con.send((new LoadingStateEvent(false)).toBytes());
    }
    if (Log.loggingDebug) {
      Log.debug("processLogin: During login, perceptionCount is " + perceptionCount);
      Log.debug("processLogin: spawned player, master playerOid=" + playerOid);
    }
    if (Log.loggingDebug)
      Log.debug("processLogin: sending over instance information for player " + playerOid + ", instance=" + instanceInfo.name + ", instanceOid=" + instanceInfo.oid);
    updateInstancePerception(player.getOid(), null, instanceInfo.oid, instanceInfo.name);
    return true;
  }
 
  public ProxyLoginCallback getProxyLoginCallback() {
    return this.proxyLoginCallback;
  }
 
  public void setProxyLoginCallback(ProxyLoginCallback callback) {
    this.proxyLoginCallback = callback;
  }
 
  private boolean instanceEntryAllowed(OID playerOid, OID instanceOid, Point location) {
    if (instanceOid == null)
      return false;
    return this.instanceEntryCallback.instanceEntryAllowed(playerOid, instanceOid, location);
  }
 
  public InstanceEntryCallback getInstanceEntryCallback() {
    return this.instanceEntryCallback;
  }
 
  public void setInstanceEntryCallback(InstanceEntryCallback callback) {
    this.instanceEntryCallback = callback;
  }
 
  public void processRequestQuestInfo(ClientConnection con, RequestQuestInfo event) {
    OID npcOid = event.getQuestNpcOid();
    Player player = verifyPlayer("processRequestQuestInfo", (Event)event, con);
    if (Log.loggingDebug)
      Log.debug("processRequestQuestInfo: player=" + player + ", npc=" + npcOid);
    QuestClient.requestQuestInfo(npcOid, player.getOid());
  }
 
  public void processQuestResponse(ClientConnection con, QuestResponse event) {
    Player player = verifyPlayer("processQuestResponse", (Event)event, con);
    boolean acceptStatus = event.getResponse();
    OID npcOid = event.getQuestNpcOid();
    OID questOid = event.getQuestId();
    if (Log.loggingDebug)
      Log.debug("processQuestResponse: player=" + player + ", npcOid=" + npcOid + ", acceptStatus=" + acceptStatus);
    QuestClient.QuestResponseMessage msg = new QuestClient.QuestResponseMessage(npcOid, player.getOid(), questOid, acceptStatus);
    Engine.getAgent().sendBroadcast((Message)msg);
  }
 
  public void processReqConcludeQuest(ClientConnection con, ConcludeQuest event) {
    Player player = verifyPlayer("processReqConcludeQuest", (Event)event, con);
    OID mobOid = event.getQuestNpcOid();
    if (Log.loggingDebug)
      Log.debug("processReqConclude: player=" + player + ", mobOid=" + mobOid);
    QuestClient.requestConclude(mobOid, player.getOid());
  }
 
  public void connectionReset(ClientConnection con) {
    Player player = (Player)con.getAssociation();
    if (player == null) {
      Log.info("ProxyPlugin: DISCONNECT remote=" + con);
      return;
    }
    if (Log.loggingInfo) {
      Log.info("ProxyPlugin: DISCONNECT remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName() + " player=" + player);
      Log.info("ProxyPlugin: DISCONNECT remote=" + con + " player=" + player);
    }
    this.playerManager.logout(player);
    ConnectionResetMessage message = new ConnectionResetMessage(this, con, player);
    message.setEnqueueTime();
    this.messageQQ.insert(player, message);
  }
 
  protected void processConnectionResetInternal(ConnectionResetMessage message) {
    long startTime = System.currentTimeMillis();
    ClientConnection con = message.getConnection();
    Player player = message.getPlayer();
    OID playerOid = player.getOid();
    if (Log.loggingInfo)
      Log.info("ProxyPlugin: LOGOUT_BEGIN remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName());
    if (player.getStatus() != 3) {
      log.error("processConnectionReset: player status is " + Player.statusToString(player.getStatus()) + " should be " + Player.statusToString(3));
      player.setStatus(3);
    }
    try {
      try {
        if (!WorldManagerClient.despawn(playerOid))
          log.warn("processConnectionReset: despawn player failed for " + playerOid);
      } catch (Exception e) {
        log.warn("processConnectionReset: despawn player failed for " + playerOid + " " + e);
      }
      if (Log.loggingDebug)
        Log.debug("processConnectionResetInternal Removing perceptionFilter for palyer: " + playerOid);
      if (this.perceptionFilter.removeTarget(playerOid)) {
        FilterUpdate filterUpdate = new FilterUpdate(1);
        filterUpdate.removeFieldValue(1, playerOid);
        if (Log.loggingDebug)
          Log.debug("processConnectionResetInternal Removing perceptionFilter applyFilterUpdate for palyer: " + playerOid);
        Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
        if (Log.loggingDebug)
          Log.debug("processConnectionResetInternal Removing responderFilter for palyer: " + playerOid);
        this.responderFilter.removeTarget(playerOid);
        this.responderFilter2.removeTarget(playerOid);
        if (Log.loggingDebug)
          Log.debug("processConnectionResetInternal Removing perceptionFilter applyFilterUpdate for palyer: " + playerOid);
        Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
        Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
      }
      LogoutMessage logoutMessage = new LogoutMessage(playerOid, player.getName());
      if (Log.loggingDebug)
        Log.debug("processConnectionResetInternal: Send LogoutMessage for player: " + playerOid + "  and wait for response");
      AsyncRPCCallback asyncRPCCallback = new AsyncRPCCallback(player, "processLogout: got LogoutMessage response");
      int expectedResponses = Engine.getAgent().sendBroadcastRPC((Message)logoutMessage, (ResponseCallback)asyncRPCCallback);
      if (Log.loggingDebug)
        Log.debug("processConnectionResetInternal: Send LogoutMessage for player: " + playerOid + "  and wait for response expectedResponses=" + expectedResponses);
      asyncRPCCallback.waitForResponses(expectedResponses);
      OID accountID = this.aDB.getAccountForCharacter(playerOid);
      if (Log.loggingDebug)
        Log.debug("Removing connection from client connection map for account: " + accountID);
      if (this.clientConnections.containsKey(accountID) && ((ClientConnection)this.clientConnections.get(accountID)).isOpen()) {
        Prometheus.registry().counter("rdp_connection_closed", new String[] { "reason", "internal_reset" }).increment();
        ((ClientConnection)this.clientConnections.get(accountID)).close();
      }
      this.clientConnections.remove(accountID);
      if (!ObjectManagerClient.unloadObject(playerOid).booleanValue())
        log.warn("processConnectionReset: unloadObject failed oid=" + playerOid);
    } catch (NoRecipientsException nre) {
      log.exception("ProxyPlugin.processConnectionResetInternal(): NoRecipientsException ", (Exception)nre);
    } catch (RPCTimeoutException nre) {
      log.exception("ProxyPlugin.processConnectionResetInternal(): RPCTimeoutException ", (Exception)nre);
    } catch (Exception nre) {
      log.exception("ProxyPlugin.processConnectionResetInternal(): Exception ", nre);
    }
    this.messageQQ.removeKey(player);
    this.eventQQ.removeKey(player);
    con.closeAggregator();
    this.playerManager.removeStaticPerception(player, playerOid);
    this.playerManager.removePlayer(playerOid);
    if (Log.loggingInfo)
      Log.info("ProxyPlugin: LOGOUT_END remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName() + " in-queue=" + (startTime - message.getEnqueueTime()) + " processing=" + (System.currentTimeMillis() - startTime) + " nPlayers=" + this.playerManager.getPlayerCount());
    synchronized (player) {
      player.clearConnection();
      player.notifyAll();
    }
  }
 
  protected void processPlayerHa(ClientConnection con, PlayerHaEvent event) {
    if (Log.loggingDebug)
      Log.debug("processPlayerHa: got dir loc orient event: " + event);
    Player player = verifyPlayer("processPlayerHa", (Event)event, con);
    long stime = System.currentTimeMillis();
    long ctime = event.getTime();
    long lctime = 0L;
    long lstime = 0L;
    try {
      lctime = ((Long)this.playerLastClientTime.get(player.getOid())).longValue();
    } catch (Exception exception) {}
    try {
      lstime = ((Long)this.playerLastServerTime.get(player.getOid())).longValue();
    } catch (Exception exception) {}
    this.playerLastClientTime.put(player.getOid(), Long.valueOf(event.getTime()));
    this.playerLastServerTime.put(player.getOid(), Long.valueOf(stime));
    if (lctime > 0L && lstime > 0L && stime - lstime < SpeedhackMinDiff) {
      log.error("SPEEDHACK detected plyOid=" + player.getOid() + " Ct=" + ctime + " LCT=" + lctime + " ST=" + stime + " LST=" + lstime + " dst=" + (stime - lstime) + " dct=" + (ctime - lctime));
      long count = 0L;
      try {
        count = ((Long)this.playerSpeedHackCount.get(player.getOid())).longValue();
      } catch (Exception exception) {}
      count++;
      this.playerSpeedHackCount.put(player.getOid(), Long.valueOf(count));
      long fdtime = 0L;
      try {
        fdtime = ((Long)this.playerFirstSpeedHackTime.get(player.getOid())).longValue();
      } catch (Exception exception) {}
      if (fdtime == 0L) {
        fdtime = stime;
        this.playerFirstSpeedHackTime.put(player.getOid(), Long.valueOf(fdtime));
      }
      if (SpeedhackChatMsg.length() > 1) {
        ChatClient.TargetedComMessage comMsg = new ChatClient.TargetedComMessage();
        comMsg.setString(SpeedhackChatMsg);
        comMsg.setChannel(0);
        comMsg.setChatterName("Admin");
        comMsg.setTarget(player.getOid());
        Engine.getAgent().sendBroadcast((Message)comMsg);
      }
      HashMap<String, Serializable> logData = new HashMap<>();
      logData.put("serverDeltaTime", Long.valueOf(stime - lstime));
      logData.put("clientDeltaTime", Long.valueOf(ctime - lctime));
      logData.put("firstDetection", Long.valueOf(fdtime));
      logData.put("count", Long.valueOf(count));
      DataLoggerClient.logData("SPEEDHACK", player.getOid(), null, null, logData);
      if (count > SpeedhackCountToDisconect) {
        Prometheus.registry().counter("rdp_connection_closed", new String[] { "reason", "speed_hack" }).increment();
        con.close();
        this.playerLastClientTime.remove(player.getOid());
        this.playerLastServerTime.remove(player.getOid());
        this.playerFirstSpeedHackTime.remove(player.getOid());
        this.playerSpeedHackCount.remove(player.getOid());
      }
    }
  }
 
  protected void processDirLocOrient(ClientConnection con, DirLocOrientEvent event) {
    if (Log.loggingDebug)
      Log.debug("processDirLocOrient: got dir loc orient event: " + event);
    Player player = verifyPlayer("processDirLoc", (Event)event, con);
    BasicWorldNode wnode = new BasicWorldNode();
    wnode.setDir(event.getDir());
    wnode.setLoc(event.getLoc());
    wnode.setOrientation(event.getQuaternion());
    wnode.time = event.getTime();
    wnode.mid = event.getId();
    wnode.cid = event.getUId();
    WorldManagerClient.updateWorldNode(player.getOid(), wnode);
  }
 
  protected void processCom(ClientConnection con, ComEvent event) {
    Player player = verifyPlayer("processCom", (Event)event, con);
    if (Log.loggingInfo)
      Log.info("ProxyPlugin: CHAT_SENT player=" + player + " channel=" + event.getChannelId() + " msg=[" + event.getMessage() + "]");
    log.debug("processCom: CHAT_SENT");
    if (this.aDB.isOnBlackList(player.getOid(), event.getObjectOid()))
      return;
    incrementChatCount();
    ChatClient.sendChatMsg(player.getOid(), player.getName(), event.getChannelId(), event.getMessage());
  }
 
  protected void processCommand(ClientConnection con, CommandEvent event) {
    RegisteredCommand command;
    Player player = verifyPlayer("processCommand", (Event)event, con);
    String cmd = event.getCommand().split(" ")[0];
    if (Log.loggingDebug)
      log.debug("processCommand: cmd=" + cmd + ", fullCmd=" + event.getCommand());
    this.commandMapLock.lock();
    try {
      command = this.commandMap.get(cmd);
    } finally {
      this.commandMapLock.unlock();
    }
    if (command == null) {
      Log.warn("processCommand: no parser for command: " + event.getCommand());
      command = this.commandMap.get("/unknowncmd");
      if (command != null) {
        Engine.setCurrentPlugin(this);
        command.parser.parse(event);
        Engine.setCurrentPlugin(null);
      }
      return;
    }
    Engine.setCurrentPlugin(this);
    if (command.access.allowed(event, this)) {
      command.parser.parse(event);
    } else {
      Log.warn("Player " + player + " not allowed to run command '" + event.getCommand() + "'");
    }
    Engine.setCurrentPlugin(null);
  }
 
  protected void processAutoAttack(ClientConnection con, AutoAttackEvent event) {
    CombatClient.autoAttack(event.getAttackerOid(), event.getTargetOid(), event.getAttackStatus());
  }
 
  protected void processActivateItem(ClientConnection con, ActivateItemEvent event) {
    InventoryClient.activateObject(event.getItemOid(), event.getObjectOid(), event.getTargetOid());
  }
 
  protected void processAbilityStatusEvent(ClientConnection con, AbilityStatusEvent event) {
    Player player = (Player)con.getAssociation();
    AbilityStatusMessage msg = new AbilityStatusMessage(CombatClient.MSG_TYPE_ABILITY_STATUS, player.getOid(), event.getPropertyMap());
    Engine.getAgent().sendBroadcast((Message)msg);
  }
 
  protected void processLogout(ClientConnection con, LogoutEvent event) {}
 
  protected void processSceneLoaded(ClientConnection con, SceneLoadedEvent event) {
    Player player = (Player)con.getAssociation();
    player.sceneLoading(false);
    if (Log.loggingDebug)
      Log.debug("SCENE: sceneLoading set to false for player: " + player.getOid());
  }
 
  protected void processExtensionMessageEvent(ClientConnection con, ExtensionMessageEvent event) {
    String key = (String)event.getPropertyMap().get("ext_msg_subtype");
    OID target = event.getTargetOid();
    Player player = (Player)con.getAssociation();
    if (Log.loggingDebug)
      Log.debug("processExtensionMessageEvent: " + player + " subType=" + key + " target=" + target);
    List<ProxyExtensionHook> proxyHookList = this.extensionHooks.get(key);
    if (proxyHookList != null) {
      for (ProxyExtensionHook hook : proxyHookList)
        hook.processExtensionEvent(event, player, this);
      return;
    }
    if (target != null) {
      WorldManagerClient.TargetedExtensionMessage msg = new WorldManagerClient.TargetedExtensionMessage(WorldManagerClient.MSG_TYPE_EXTENSION, target, player.getOid(), event.getClientTargeted(), event.getPropertyMap());
      if (event.getClientTargeted().booleanValue()) {
        msg.setMsgType(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
        if (allowClientToClientMessage(player, target, msg))
          Engine.getAgent().sendBroadcast((Message)msg);
      } else {
        MessageType msgType = getExtensionMessageType(key);
        if (msgType == null) {
          Log.error("processExtensionMessageEvent: key '" + key + "' has no corresponding MessageType");
          return;
        }
        msg.setMsgType(msgType);
        Engine.getAgent().sendBroadcast((Message)msg);
      }
    } else {
      MessageType msgType = getExtensionMessageType(key);
      if (msgType == null) {
        Log.error("processExtensionMessageEvent: key '" + key + "' has no corresponding MessageType");
        return;
      }
      WorldManagerClient.ExtensionMessage msg = new WorldManagerClient.ExtensionMessage(msgType, player.getOid(), event.getPropertyMap());
      Engine.getAgent().sendBroadcast((Message)msg);
    }
  }
 
  public void registerExtensionSubtype(String subtype, MessageType type) {
    this.extensionMessageRegistry.put(subtype, type);
  }
 
  public MessageType unregisterExtensionSubtype(String subtype) {
    return this.extensionMessageRegistry.remove(subtype);
  }
 
  public MessageType getExtensionMessageType(String subtype) {
    return this.extensionMessageRegistry.get(subtype);
  }
 
  public boolean allowClientToClientMessage(Player sender, OID targetOid, WorldManagerClient.TargetedExtensionMessage message) {
    return this.defaultAllowClientToClientMessage;
  }
 
  protected boolean specialCaseNewProcessing(PerceptionMessage.ObjectNote objectNote, Player player) {
    long start = System.currentTimeMillis();
    ClientConnection con = player.getConnection();
    OID objOid = objectNote.getSubject();
    ObjectType objType = objectNote.getObjectType();
    if (objType == ObjectTypes.light) {
      Log.debug("specialCaseNewProcessing: got a light object");
      LightData lightData = (LightData)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, Light.LightDataPropertyKey);
      if (Log.loggingDebug)
        Log.debug("specialCaseNewProcessing: light data=" + lightData);
      NewLightEvent lightEvent = new NewLightEvent(player.getOid(), objOid, lightData);
      con.send(lightEvent.toBytes());
      return true;
    }
    if (objType.equals(WorldManagerClient.TEMPL_OBJECT_TYPE_TERRAIN_DECAL)) {
      Log.debug("specialCaseNewProcessing: got a terrain decal object");
      TerrainDecalData decalData = (TerrainDecalData)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
      if (Log.loggingDebug)
        Log.debug("specialCaseNewProcessing: terrain decal data=" + decalData);
      NewTerrainDecalEvent decalEvent = new NewTerrainDecalEvent(objOid, decalData);
      con.send(decalEvent.toBytes());
      return true;
    }
    if (objType.equals(WorldManagerClient.TEMPL_OBJECT_TYPE_POINT_SOUND)) {
      Log.debug("specialCaseNewProcessing: got a point sound object");
      List<SoundData> soundData = (List<SoundData>)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, WorldManagerClient.TEMPL_SOUND_DATA_LIST);
      if (Log.loggingDebug)
        Log.debug("specialCaseNewProcessing: sound data=" + soundData);
      WorldManagerClient.SoundMessage soundMsg = new WorldManagerClient.SoundMessage(objOid);
      soundMsg.setSoundData(soundData);
      con.send(soundMsg.toBuffer());
      return true;
    }
    WorldManagerClient.PerceptionInfo perceptionInfo = (WorldManagerClient.PerceptionInfo)objectNote.getObjectInfo();
    if (perceptionInfo.objectInfo == null)
      return true;
    WorldManagerClient.MobPathMessage pathMsg = (WorldManagerClient.MobPathMessage)perceptionInfo.objectInfo.getProperty(WorldManagerClient.MOB_PATH_PROPERTY);
    if (Log.loggingDebug)
      Log.debug("INFO: MobPathMessage special case with player/npc: " + perceptionInfo.objectInfo.name);
    con.send(perceptionInfo.objectInfo.toBuffer(player.getOid()));
    if (Log.loggingDebug)
      Log.debug("INFO: specialCaseNewProcessing " + perceptionInfo.displayContext);
    if (perceptionInfo.displayContext != null) {
      ModelInfoEvent modelInfoEvent = new ModelInfoEvent(objOid);
      modelInfoEvent.setDisplayContext(perceptionInfo.displayContext);
      con.send(modelInfoEvent.toBytes());
    } else if (Log.loggingDebug) {
      Log.debug("No display context for " + objOid + " " + perceptionInfo.objectInfo);
    }
    if (pathMsg != null)
      if (pathMsg.pathExpired()) {
        if (Log.loggingDebug)
          Log.debug("specialCaseNewProcessing: for mob " + objOid + ", last mob path expired " + pathMsg.toString());
      } else {
        if (Log.loggingDebug)
          Log.debug("specialCaseNewProcessing: for mob " + objOid + ", sending last mob path " + pathMsg.toString());
        AOByteBuffer pathBuf = pathMsg.toBuffer();
        con.send(pathBuf);
      }
    Map<String, DisplayContext> childMap = null;
    if (perceptionInfo.displayContext != null)
      childMap = perceptionInfo.displayContext.getChildDCMap();
    if (childMap != null && !childMap.isEmpty()) {
      for (String slot : childMap.keySet()) {
        DisplayContext attachDC = childMap.get(slot);
        if (attachDC == null)
          throw new AORuntimeException("attach DC is null for obj: " + objOid);
        OID attacheeOID = attachDC.getObjRef();
        if (attacheeOID == null)
          throw new AORuntimeException("attachee oid is null for obj: " + objOid);
        if (Log.loggingDebug)
          Log.debug("specialCaseNewProcessing: sending attach message to " + player.getOid() + " attaching to obj " + objOid + ", object being attached=" + attacheeOID + " to slot " + slot + ", attachmentDC=" + attachDC);
        AttachEvent event = new AttachEvent(objOid, attacheeOID, slot, attachDC);
        con.send(event.toBytes());
      }
      if (Log.loggingDebug)
        Log.debug("specialCaseNewProcessing: done with processing attachments");
    }
    long finish = System.currentTimeMillis();
    if (Log.loggingDebug)
      Log.debug("specialCaseNewProcessing: finished.\tplayerOid=" + player.getOid() + ", oid=" + objOid + " in " + (finish - start) + " ms");
    return false;
  }
 
  protected boolean specialCaseFreeProcessing(PerceptionMessage.ObjectNote objectNote, Player player) {
    if (player.getOid().equals(objectNote.getSubject())) {
      Log.debug("ignoring free object message to self");
      return true;
    }
    ClientConnection con = player.getConnection();
    if (!con.isOpen())
      con = null;
    OID objOid = objectNote.getSubject();
    if (objectNote.getObjectType() == ObjectTypes.road) {
      if (Log.loggingDebug)
        Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", roadSegmentOid=" + objOid);
      handleFreeRoad(con, objOid);
      return true;
    }
    if (objectNote.getObjectType().equals(WorldManagerClient.TEMPL_OBJECT_TYPE_TERRAIN_DECAL)) {
      if (Log.loggingDebug)
        Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", decalOid=" + objOid);
      FreeTerrainDecalEvent decalEvent = new FreeTerrainDecalEvent(objOid);
      if (con != null)
        con.send(decalEvent.toBytes());
      return true;
    }
    if (Log.loggingDebug)
      Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", objOid=" + objOid);
    NotifyFreeObjectEvent freeEvent = new NotifyFreeObjectEvent(player.getOid(), objOid);
    if (con != null)
      con.send(freeEvent.toBytes());
    return false;
  }
 
  protected void handleFreeRoad(ClientConnection con, OID objOid) {
    WorldManagerClient.FreeRoadMessage freeRoadMsg = new WorldManagerClient.FreeRoadMessage(objOid);
    AOByteBuffer buf = freeRoadMsg.toBuffer();
    if (con != null)
      con.send(buf);
  }
 
  public static void addStaticPerception(OID playerOid, OID oid) {
    addStaticPerception(playerOid, oid, null, null, false);
  }
 
  public static void addStaticPerception(OID oid, OID oid2, String name, ObjectType type) {
    addStaticPerception(oid, oid2, name, type, true);
  }
 
  private static void addStaticPerception(OID playerOid, OID oid, String name, ObjectType type, boolean hasObjectInfo) {
    AddStaticPerceptionMessage message = new AddStaticPerceptionMessage(MSG_TYPE_ADD_STATIC_PERCEPTION);
    message.setTarget(playerOid);
    message.setSubject(oid);
    message.setName(name);
    message.setType(type);
    message.setHasObjectInfo(hasObjectInfo);
    Engine.getAgent().sendBroadcast((Message)message);
  }
 
  public static void removeStaticPerception(OID playerOid, OID oid) {
    TargetMessage message = new TargetMessage(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
    message.setTarget(playerOid);
    message.setSubject(oid);
    Engine.getAgent().sendBroadcast((Message)message);
  }
 
  protected void processPlayerIgnoreList(Player player) {
    if (player.getStatus() == 3) {
      Log.error("ProxyPlugin.processPlayerIgnoreList: Aborting... player.getStatus() is STATUS_LOGOUT");
      return;
    }
    sendPlayerIgnoreList(player);
  }
 
  protected void sendPlayerIgnoreList(Player player) {
    String missing = " Missing ";
  }
 
  public void updateIgnoredOids(Player player, List<OID> nowIgnored, List<OID> noLongerIgnored) {}
 
  public List<Object> matchingPlayers(Player player, String playerName, Boolean exactMatch) {
    boolean match = (exactMatch == null) ? true : exactMatch.booleanValue();
    List<Object> matchLists = Engine.getDatabase().getOidsAndNamesMatchingName(playerName, match);
    List<OID> oids = (List<OID>)matchLists.get(0);
    List<String> names = (List<String>)matchLists.get(1);
    if (Log.loggingDebug)
      log.debug("ProxyPlugin.matchingPlayers: For player " + player.getOid() + ", found " + ((oids == null) ? 0 : oids.size()) + " players: " + Database.makeOidCollectionString(oids) + " " + (match ? "exactly matching" : "starting with") + " name '" + playerName + "':" + Database.makeNameCollectionString(names));
    return matchLists;
  }
 
  public boolean isOnBlockList2(OID playerOid, OID targetOid) {
    if (Log.loggingDebug)
      log.debug("IsOnBlockList: SocialPlugin  started for: " + playerOid);
    boolean isOnBlockList = this.aDB.isOnBlackList(playerOid, targetOid);
    if (isOnBlockList) {
      String targetName = (WorldManagerClient.getObjectInfo(targetOid)).name;
      EventMessageHelper.SendErrorEvent(playerOid, "ErrorPlayerOnBlockList", 0, targetName);
    } else {
      isOnBlockList = this.aDB.isOnBlackList(targetOid, playerOid);
      if (isOnBlockList) {
        String targetName = (WorldManagerClient.getObjectInfo(targetOid)).name;
        EventMessageHelper.SendErrorEvent(playerOid, "ErrorPlayerYourOnBlockList", 0, targetName);
      }
    }
    if (Log.loggingDebug)
      log.debug("IsOnBlockList: SocialPlugin  finished for: " + playerOid);
    return isOnBlockList;
  }
 
  private boolean isPlayerConnectionValid(Player player) {
    ClientConnection con = player.getConnection();
    return (con != null && con.isOpen());
  }
 
  public static OID handleFullInstance(int instanceTemplateID, InstanceClient.InstanceInfo instanceInfo) {
    OID instanceOid;
    if (Log.loggingDebug)
      Log.debug("POP: instance full with template: " + instanceTemplateID);
    int instanceNum = 1;
    String instanceName = "";
    InstanceTemplate island = InstanceClient.getInstanceTemplate(instanceTemplateID);
    while (true) {
      instanceName = island.getName() + "_" + instanceNum;
      instanceOid = InstanceClient.getInstanceOid(instanceName);
      if (instanceOid != null) {
        instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145);
        if (instanceInfo.populationLimit < 1 || instanceInfo.playerPopulation < instanceInfo.populationLimit)
          break;
      } else {
        Template overrideTemplate = new Template();
        overrideTemplate.put(Namespace.INSTANCE, "name", instanceName);
        overrideTemplate.setName(instanceName);
        instanceOid = InstanceClient.createInstance(instanceTemplateID, overrideTemplate);
        if (instanceOid != null)
          break;
      }
      instanceNum++;
    }
    return instanceOid;
  }
 
  private void updateInstancePerception(OID playerOid, OID prevInstanceOid, OID destInstanceOid, String destInstanceName) {
    if (prevInstanceOid != null)
      removeStaticPerception(playerOid, prevInstanceOid);
    addStaticPerception(playerOid, destInstanceOid, destInstanceName, ObjectTypes.instance);
  }
 
  protected void pushInstanceRestorePoint(Player player, BasicWorldNode loc) {
    OID playerOid = player.getOid();
    if (Log.loggingDebug)
      log.debug("pushInstanceRestorePoint " + playerOid);
    InstanceRestorePoint restorePoint = new InstanceRestorePoint();
    restorePoint.setInstanceOid(loc.getInstanceOid());
    restorePoint.setLoc(loc.getLoc());
    restorePoint.setOrientation(loc.getOrientation());
    InstanceClient.InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(loc.getInstanceOid(), 8);
    restorePoint.setInstanceID(instanceInfo.templateID);
    LinkedList<Object> restoreStack = (LinkedList<Object>)EnginePlugin.getObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack");
    if (restoreStack == null)
      restoreStack = new LinkedList();
    restoreStack.add(restorePoint);
    EnginePlugin.setObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack", restoreStack);
  }
 
  protected void sendOceanData(OceanData oceanData, Player player) {
    ClientParameter.ClientParameterMessage clientParameterMessage = new ClientParameter.ClientParameterMessage(player.getOid());
    clientParameterMessage.setProperty("Ocean.DisplayOcean", oceanData.displayOcean.toString());
    if (oceanData.useParams != null)
      clientParameterMessage.setProperty("Ocean.UseParams", oceanData.useParams.toString());
    if (oceanData.waveHeight != null)
      clientParameterMessage.setProperty("Ocean.WaveHeight", oceanData.waveHeight.toString());
    if (oceanData.seaLevel != null)
      clientParameterMessage.setProperty("Ocean.SeaLevel", oceanData.seaLevel.toString());
    if (oceanData.bumpScale != null)
      clientParameterMessage.setProperty("Ocean.BumpScale", oceanData.bumpScale.toString());
    if (oceanData.bumpSpeedX != null)
      clientParameterMessage.setProperty("Ocean.BumpSpeedX", oceanData.bumpSpeedX.toString());
    if (oceanData.bumpSpeedZ != null)
      clientParameterMessage.setProperty("Ocean.BumpSpeedZ", oceanData.bumpSpeedZ.toString());
    if (oceanData.textureScaleX != null)
      clientParameterMessage.setProperty("Ocean.TextureScaleX", oceanData.textureScaleX.toString());
    if (oceanData.textureScaleZ != null)
      clientParameterMessage.setProperty("Ocean.TextureScaleZ", oceanData.textureScaleZ.toString());
    if (oceanData.deepColor != null)
      clientParameterMessage.setProperty("Ocean.DeepColor", oceanData.deepColor.toString());
    if (oceanData.shallowColor != null)
      clientParameterMessage.setProperty("Ocean.ShallowColor", oceanData.shallowColor.toString());
    player.getConnection().send(clientParameterMessage.toBuffer(player.getVersion()));
  }
 
  protected Player verifyPlayer(String context, Event event, ClientConnection con) {
    Player player = (Player)con.getAssociation();
    if (!player.getOid().equals(event.getObjectOid()))
      throw new AORuntimeException(context + ": con doesn't match player " + player + " against eventOid " + event.getObjectOid());
    return player;
  }
 
  public void incrementChatCount() {
    this.chatSentCount++;
  }
 
  public void incrementPrivateChatCount() {
    this.privateChatSentCount++;
  }
 
  protected static final Logger log = new Logger("ProxyPlugin");
 
  PlayerMessageCallback playerMessageCallback;
 
  protected PlayerManager playerManager;
 
  protected ConcurrentHashMap<OID, String> playersOnlineList;
 
  protected ConcurrentHashMap<OID, String> playersOnlineOnProxy;
 
  protected TimeHistogram proxyQueueHistogram;
 
  protected TimeHistogram proxyCallbackHistogram;
 
  protected List<MessageType> extraPlayerMessageTypes;
 
  private ProxyLoginCallback proxyLoginCallback;
 
  private InstanceEntryCallback instanceEntryCallback;
 
  private int instanceEntryCount;
 
  private int chatSentCount;
 
  private int privateChatSentCount;
 
  public static final MessageType MSG_TYPE_VOICE_PARMS = MessageType.intern("ao.VOICE_PARMS");
 
  public static final MessageType MSG_TYPE_PLAYER_PATH_REQ = MessageType.intern("ao.PLAYER_PATH_REQ");
 
  public static final MessageType MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST = MessageType.intern("ao.UPDATE_PLAYER_IGNORE_LIST");
 
  public static final MessageType MSG_TYPE_GET_MATCHING_PLAYERS = MessageType.intern("ao.GET_MATCHING_PLAYERS");
 
  public static final MessageType MSG_TYPE_PLAYER_IGNORE_LIST = MessageType.intern("ao.PLAYER_IGNORE_LIST");
 
  public static final MessageType MSG_TYPE_PLAYER_IGNORE_LIST_REQ = MessageType.intern("ao.PLAYER_IGNORE_LIST_REQ");
 
  public static final MessageType MSG_TYPE_RELAY_UPDATE_PLAYER_IGNORE_LIST = MessageType.intern("ao.RELAY_UPDATE_PLAYER_IGNORE_LIST");
 
  public static final MessageType MSG_TYPE_GET_PLAYER_LOGIN_STATUS = MessageType.intern("ao.GET_PLAYER_LOGIN_STATUS");
 
  public static final MessageType MSG_TYPE_LOGOUT_PLAYER = MessageType.intern("ao.LOGOUT_PLAYER");
 
  public static final MessageType MSG_TYPE_ADD_STATIC_PERCEPTION = MessageType.intern("ao.ADD_STATIC_PERCEPTION");
 
  public static final MessageType MSG_TYPE_REMOVE_STATIC_PERCEPTION = MessageType.intern("ao.REMOVE_STATIC_PERCEPTION");
 
  public static final MessageType MSG_TYPE_LOGIN_SPAWNED = MessageType.intern("ao.LOGIN_SPAWNED");
 
  public static final MessageType MSG_TYPE_ACCOUNT_LOGIN = MessageType.intern("ao.ACCOUNT_LOGIN");
 
  public static final MessageType MSG_TYPE_SERVER_SHUTDOWN_MESSAGE = MessageType.intern("server.Shutdown_Message");
 
  public static final MessageType MSG_TYPE_SERVER_SHUTDOWN = MessageType.intern("server.Shutdown");
 
  public static final MessageType MSG_TYPE_SERVER_RELOAD = MessageType.intern("server.Reload");
 
  protected static String voiceServerHost = "";
 
  protected static Integer voiceServerPort = null;
 
  public String serverCapabilitiesSentToClient;
 
  public static int DiffTimeToSkipDirLocOrientMessage = 500;
 
  static int serverSocketReceiveBufferSize = 8388608;
 
  public static int MaxConcurrentUsers = 2000;
 
  public static int restriction_level = 0;
 
  public static int idleTimeout = 900;
 
  public static int silenceTimeout = 30;
 
  public static int silenceLoadingTimeout = 900;
 
  public static int maxMessagesBeforeConnectionReset = 2000;
 
  public static int maxByteCountBeforeConnectionReset = 1000000;
 
  public String capacityError;
 
  public String tokenError;
 
  public static String SpeedhackChatMsg = "Detected Speedhack";
 
  public static int SpeedhackCountToDisconect = 10;
 
  public static int SpeedhackMinDiff = 8000;
 
  private ClientTCPMessageIO clientTCPMessageIO;
 
  Set<OID> adminSet;
 
  Map<OID, ClientConnection> clientConnections;
 
  Set<String> filteredProps;
 
  Set<String> playerSpecificProps;
 
  Set<String> cachedPlayerSpecificFilterProps;
 
  String serverVersion;
 
  protected Map<String, List<ProxyExtensionHook>> extensionHooks;
 
  private int connectionLimit;
 
  boolean devMode;
 
  public void addAdmin(OID oid) {
    if (Log.loggingDebug)
      log.debug("ProxyPlugin.addAdmin: adding oid " + oid);
    this.lock.lock();
    try {
      this.adminSet.add(oid);
    } finally {
      this.lock.unlock();
    }
  }
 
  public Set<OID> getAdmins() {
    this.lock.lock();
    try {
      return new HashSet<>(this.adminSet);
    } finally {
      this.lock.unlock();
    }
  }
 
  public boolean isAdmin(OID playerOid) {
    this.lock.lock();
    try {
      if (playerOid == null)
        return false;
      AccountDatabase aDB = new AccountDatabase(false);
      int status = aDB.getCharacterAccountStatus(playerOid);
      return (status == 5);
    } finally {
      this.lock.unlock();
    }
  }
 
  public int GetConnectionLimit() {
    return this.connectionLimit;
  }
 
  protected Object createMBeanInstance() {
    return new ProxyJMX(this);
  }
 
  private String getTemp() {
    return "47bedc488b0106b2219dd2e2ff5524fd";
  }
}
нет, тебе проще будет закинуть что бы тебе сделали мне кажеться
 
atavism/server/plugins/proxyplugin
 

Вложения

  • dist.rar
    4,4 МБ · Просмотры: 6

Вложения

  • lic.zip
    1,6 МБ · Просмотры: 13
Не знаю на скок правильно декомпилировании файл .

Помогите снять проверку лицензии. *


Java:
package atavism.server.plugins;

import atavism.agis.database.AccountDatabase;
import atavism.agis.database.ContentDatabase;
import atavism.agis.events.AbilityStatusEvent;
import atavism.agis.events.AbilityStatusMessage;
import atavism.agis.events.ConcludeQuest;
import atavism.agis.events.QuestResponse;
import atavism.agis.events.RequestQuestInfo;
import atavism.agis.plugins.AnimationClient;
import atavism.agis.plugins.ChatClient;
import atavism.agis.plugins.CombatClient;
import atavism.agis.plugins.DataLoggerClient;
import atavism.agis.plugins.QuestClient;
import atavism.agis.plugins.SocialClient;
import atavism.agis.plugins.ChatClient.TargetedComMessage;
import atavism.agis.plugins.QuestClient.QuestResponseMessage;
import atavism.agis.util.EventMessageHelper;
import atavism.agis.util.HelperFunctions;
import atavism.management.Management;
import atavism.msgsys.FilterUpdate;
import atavism.msgsys.Message;
import atavism.msgsys.MessageType;
import atavism.msgsys.MessageTypeFilter;
import atavism.msgsys.NoRecipientsException;
import atavism.msgsys.RPCTimeoutException;
import atavism.msgsys.SubjectMessage;
import atavism.msgsys.TargetMessage;
import atavism.server.engine.BasicWorldNode;
import atavism.server.engine.Database;
import atavism.server.engine.Engine;
import atavism.server.engine.EnginePlugin;
import atavism.server.engine.Event;
import atavism.server.engine.Namespace;
import atavism.server.engine.OID;
import atavism.server.events.ActivateItemEvent;
import atavism.server.events.AttachEvent;
import atavism.server.events.AuthorizedLoginEvent;
import atavism.server.events.AuthorizedLoginResponseEvent;
import atavism.server.events.AutoAttackEvent;
import atavism.server.events.ComEvent;
import atavism.server.events.CommandEvent;
import atavism.server.events.DirLocOrientEvent;
import atavism.server.events.ExtensionMessageEvent;
import atavism.server.events.FreeTerrainDecalEvent;
import atavism.server.events.LoadingStateEvent;
import atavism.server.events.LogoutEvent;
import atavism.server.events.ModelInfoEvent;
import atavism.server.events.NewLightEvent;
import atavism.server.events.NewTerrainDecalEvent;
import atavism.server.events.NotifyFreeObjectEvent;
import atavism.server.events.PlayerHaEvent;
import atavism.server.events.SceneLoadedEvent;
import atavism.server.events.WorldFileEvent;
import atavism.server.math.AOVector;
import atavism.server.math.Point;
import atavism.server.messages.LoginMessage;
import atavism.server.messages.LogoutMessage;
import atavism.server.messages.PerceptionFilter;
import atavism.server.messages.PerceptionTrigger;
import atavism.server.messages.PropertyMessage;
import atavism.server.messages.PerceptionMessage.ObjectNote;
import atavism.server.network.AOByteBuffer;
import atavism.server.network.ClientConnection;
import atavism.server.network.ClientTCPMessageIO;
import atavism.server.network.PacketAggregator;
import atavism.server.network.ClientConnection.AcceptCallback;
import atavism.server.network.rdp.RDPServer;
import atavism.server.network.rdp.RDPServerSocket;
import atavism.server.objects.DisplayContext;
import atavism.server.objects.InstanceEntryCallback;
import atavism.server.objects.InstanceRestorePoint;
import atavism.server.objects.InstanceTemplate;
import atavism.server.objects.Light;
import atavism.server.objects.LightData;
import atavism.server.objects.ObjectType;
import atavism.server.objects.ObjectTypes;
import atavism.server.objects.OceanData;
import atavism.server.objects.Player;
import atavism.server.objects.PlayerManager;
import atavism.server.objects.ProxyExtensionHook;
import atavism.server.objects.ProxyLoginCallback;
import atavism.server.objects.SoundData;
import atavism.server.objects.Template;
import atavism.server.objects.TerrainDecalData;
import atavism.server.objects.World;
import atavism.server.plugins.ClientParameter.ClientParameterMessage;
import atavism.server.plugins.InstanceClient.InstanceInfo;
import atavism.server.plugins.ProxyPlugin.1;
import atavism.server.plugins.ProxyPlugin.2;
import atavism.server.plugins.ProxyPlugin.3;
import atavism.server.plugins.WorldManagerClient.ExtensionMessage;
import atavism.server.plugins.WorldManagerClient.FreeRoadMessage;
import atavism.server.plugins.WorldManagerClient.MobPathMessage;
import atavism.server.plugins.WorldManagerClient.ObjectInfo;
import atavism.server.plugins.WorldManagerClient.PerceptionInfo;
import atavism.server.plugins.WorldManagerClient.SoundMessage;
import atavism.server.plugins.WorldManagerClient.TargetedExtensionMessage;
import atavism.server.telemetry.Prometheus;
import atavism.server.util.AOMeter;
import atavism.server.util.AORuntimeException;
import atavism.server.util.Base64;
import atavism.server.util.CountLogger;
import atavism.server.util.DebugUtils;
import atavism.server.util.EncryptionHelper;
import atavism.server.util.LockFactory;
import atavism.server.util.Log;
import atavism.server.util.Logger;
import atavism.server.util.ObjectLockManager;
import atavism.server.util.SQThreadPool;
import atavism.server.util.SecureToken;
import atavism.server.util.SecureTokenManager;
import atavism.server.util.ServerVersion;
import atavism.server.util.SquareQueue;
import atavism.server.util.TimeHistogram;
import atavism.server.util.CountLogger.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.Timer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

public class ProxyPlugin extends EnginePlugin implements AcceptCallback, atavism.server.network.ClientConnection.MessageCallback {
   private static int MESSAGE_QUEUE_THREADS = 16;
   private static int EVENT_QUEUE_THREADS = 16;
   private static int SLOW_EVENT_QUEUE_THREADS = 8;
   private static final int RDP_CHANNELS_COUNT = 128;
   public static final int PERCEPTION_GAIN_THRESHOLD = 20;
   CountLogger countLogger = new CountLogger("ProxyMsg", 5000, 2);
   Counter countMsgPerception;
   Counter countMsgPerceptionGain;
   Counter countMsgPerceptionLost;
   Counter countMsgUpdateWNodeIn;
   Counter countMsgUpdateWNodeOut;
   Counter countMsgPropertyIn;
   Counter countMsgPropertyOut;
   Counter countMsgTargetedProperty;
   Counter countMsgWNodeCorrectIn;
   Counter countMsgWNodeCorrectOut;
   Counter countMsgMobPathIn;
   Counter countMsgMobPathOut;
   public static boolean debugLic = false;
   protected Lock commandMapLock = LockFactory.makeLock("CommandMapLock");
   Map<String, atavism.server.plugins.ProxyPlugin.RegisteredCommand> commandMap = new HashMap();
   atavism.server.plugins.ProxyPlugin.CommandAccessCheck defaultCommandAccess = new atavism.server.plugins.ProxyPlugin.DefaultCommandAccess((1)null);
   SquareQueue<Player, Message> messageQQ = new SquareQueue("Message");
   SQThreadPool messageThreadPool = null;
   private final SquareQueue<Player, Event> eventQQ = new SquareQueue("Event");
   private SQThreadPool<Player, Event> eventThreadPool = null;
   private final SquareQueue<Player, Event> slowEventQQ = new SquareQueue("SlowEvent");
   private SQThreadPool<Player, Event> slowEventThreadPool = null;
   AOMeter clientMsgMeter = new AOMeter("ClientEventProcessorMeter");
   protected ConcurrentHashMap<OID, Long> playerLastClientTime = new ConcurrentHashMap();
   protected ConcurrentHashMap<OID, Long> playerLastServerTime = new ConcurrentHashMap();
   protected ConcurrentHashMap<OID, Long> playerFirstSpeedHackTime = new ConcurrentHashMap();
   protected ConcurrentHashMap<OID, Long> playerSpeedHackCount = new ConcurrentHashMap();
   public boolean defaultAllowClientToClientMessage = false;
   protected HashMap<String, MessageType> extensionMessageRegistry = new HashMap();
   private final ExecutorService logoutExecutor = Executors.newCachedThreadPool();
   protected AccountDatabase aDB;
   protected PerceptionFilter perceptionFilter;
   protected long perceptionSubId;
   protected PerceptionFilter responderFilter;
   protected PerceptionFilter responderFilter2;
   protected long responderSubId;
   protected long responderSubId2;
   protected int clientPort;
   protected static final Logger log = new Logger("ProxyPlugin");
   atavism.server.plugins.ProxyPlugin.PlayerMessageCallback playerMessageCallback = new atavism.server.plugins.ProxyPlugin.PlayerMessageCallback(this);
   protected PlayerManager playerManager = new PlayerManager();
   protected ConcurrentHashMap<OID, String> playersOnlineList = new ConcurrentHashMap();
   protected ConcurrentHashMap<OID, String> playersOnlineOnProxy = new ConcurrentHashMap();
   protected TimeHistogram proxyQueueHistogram = null;
   protected TimeHistogram proxyCallbackHistogram = null;
   protected List<MessageType> extraPlayerMessageTypes = null;
   private ProxyLoginCallback proxyLoginCallback = new atavism.server.plugins.ProxyPlugin.DefaultProxyLoginCallback((1)null);
   private InstanceEntryCallback instanceEntryCallback = new atavism.server.plugins.ProxyPlugin.DefaultInstanceEntryCallback((1)null);
   private int instanceEntryCount = 0;
   private int chatSentCount = 0;
   private int privateChatSentCount = 0;
   public static final MessageType MSG_TYPE_VOICE_PARMS = MessageType.intern("ao.VOICE_PARMS");
   public static final MessageType MSG_TYPE_PLAYER_PATH_REQ = MessageType.intern("ao.PLAYER_PATH_REQ");
   public static final MessageType MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST = MessageType.intern("ao.UPDATE_PLAYER_IGNORE_LIST");
   public static final MessageType MSG_TYPE_GET_MATCHING_PLAYERS = MessageType.intern("ao.GET_MATCHING_PLAYERS");
   public static final MessageType MSG_TYPE_PLAYER_IGNORE_LIST = MessageType.intern("ao.PLAYER_IGNORE_LIST");
   public static final MessageType MSG_TYPE_PLAYER_IGNORE_LIST_REQ = MessageType.intern("ao.PLAYER_IGNORE_LIST_REQ");
   public static final MessageType MSG_TYPE_RELAY_UPDATE_PLAYER_IGNORE_LIST = MessageType.intern("ao.RELAY_UPDATE_PLAYER_IGNORE_LIST");
   public static final MessageType MSG_TYPE_GET_PLAYER_LOGIN_STATUS = MessageType.intern("ao.GET_PLAYER_LOGIN_STATUS");
   public static final MessageType MSG_TYPE_LOGOUT_PLAYER = MessageType.intern("ao.LOGOUT_PLAYER");
   public static final MessageType MSG_TYPE_ADD_STATIC_PERCEPTION = MessageType.intern("ao.ADD_STATIC_PERCEPTION");
   public static final MessageType MSG_TYPE_REMOVE_STATIC_PERCEPTION = MessageType.intern("ao.REMOVE_STATIC_PERCEPTION");
   public static final MessageType MSG_TYPE_LOGIN_SPAWNED = MessageType.intern("ao.LOGIN_SPAWNED");
   public static final MessageType MSG_TYPE_ACCOUNT_LOGIN = MessageType.intern("ao.ACCOUNT_LOGIN");
   public static final MessageType MSG_TYPE_SERVER_SHUTDOWN_MESSAGE = MessageType.intern("server.Shutdown_Message");
   public static final MessageType MSG_TYPE_SERVER_SHUTDOWN = MessageType.intern("server.Shutdown");
   public static final MessageType MSG_TYPE_SERVER_RELOAD = MessageType.intern("server.Reload");
   protected static String voiceServerHost = "";
   protected static Integer voiceServerPort = null;
   public String serverCapabilitiesSentToClient = "DirLocOrient";
   public static int DiffTimeToSkipDirLocOrientMessage = 500;
   static int serverSocketReceiveBufferSize = 8388608;
   public static int MaxConcurrentUsers = 2000;
   public static int restriction_level = 0;
   public static int idleTimeout = 900;
   public static int silenceTimeout = 30;
   public static int silenceLoadingTimeout = 900;
   public static int maxMessagesBeforeConnectionReset = 2000;
   public static int maxByteCountBeforeConnectionReset = 1000000;
   public String capacityError = "Login Failed: Servers at capacity, please try again later.";
   public String tokenError = "Login Failed: Secure token invalid.";
   public static String SpeedhackChatMsg = "Detected Speedhack";
   public static int SpeedhackCountToDisconect = 10;
   public static int SpeedhackMinDiff = 8000;
   private ClientTCPMessageIO clientTCPMessageIO = null;
   Set<OID> adminSet = new HashSet();
   Map<OID, ClientConnection> clientConnections = new ConcurrentHashMap();
   Set<String> filteredProps = null;
   Set<String> playerSpecificProps = null;
   Set<String> cachedPlayerSpecificFilterProps = null;
   String serverVersion = null;
   protected Map<String, List<ProxyExtensionHook>> extensionHooks = new HashMap();
   private int connectionLimit = 0;
   boolean devMode = true;

   public ProxyPlugin() {
      super(getPluginName(), (atavism.msgsys.MessageCallback)null);
      this.setPluginType("Proxy");
      this.serverVersion = "10.7.0 " + ServerVersion.getBuildNumber();
      String MessageQueueThreadPoolSize = Engine.properties.getProperty("atavism.proxy.MessageQueueThreadPoolSize");
      if (MessageQueueThreadPoolSize != null) {
         try {
            int v = Integer.parseInt(MessageQueueThreadPoolSize);
            MESSAGE_QUEUE_THREADS = v;
         } catch (NumberFormatException var8) {
            var8.printStackTrace();
            Log.exception(var8);
         }
      }

      String EventQueueThreadPoolSize = Engine.properties.getProperty("atavism.proxy.EventQueueThreadPoolSize");
      if (EventQueueThreadPoolSize != null) {
         try {
            int v = Integer.parseInt(EventQueueThreadPoolSize);
            EVENT_QUEUE_THREADS = v;
         } catch (NumberFormatException var7) {
            var7.printStackTrace();
            Log.exception(var7);
         }
      }

      String proxy_concurrent_logins = Engine.properties.getProperty("atavism.proxy.ConcurrentLogins");
      if (proxy_concurrent_logins != null) {
         try {
            int v = Integer.parseInt(proxy_concurrent_logins);
            SLOW_EVENT_QUEUE_THREADS = v;
         } catch (NumberFormatException var6) {
            var6.printStackTrace();
            Log.exception(var6);
         }
      }

      this.messageThreadPool = new SQThreadPool(this.messageQQ, new atavism.server.plugins.ProxyPlugin.MessageCallback(this, this), MESSAGE_QUEUE_THREADS);
      this.eventThreadPool = new SQThreadPool(this.eventQQ, new atavism.server.plugins.ProxyPlugin.EventCallback(this), EVENT_QUEUE_THREADS);
      this.slowEventThreadPool = new SQThreadPool(this.slowEventQQ, new atavism.server.plugins.ProxyPlugin.EventCallback(this), SLOW_EVENT_QUEUE_THREADS);
      this.countMsgPerception = this.countLogger.addCounter("ao.PERCEPTION_INFO");
      this.countMsgPerceptionGain = this.countLogger.addCounter("Perception.gain");
      this.countMsgPerceptionLost = this.countLogger.addCounter("Perception.lost");
      this.countMsgUpdateWNodeIn = this.countLogger.addCounter("ao.UPDATEWNODE.in");
      this.countMsgUpdateWNodeOut = this.countLogger.addCounter("ao.UPDATEWNODE.out");
      this.countMsgPropertyIn = this.countLogger.addCounter("ao.PROPERTY.in");
      this.countMsgPropertyOut = this.countLogger.addCounter("ao.PROPERTY.out");
      this.countMsgTargetedProperty = this.countLogger.addCounter("ao.TARGETED_PROPERTY");
      this.countMsgWNodeCorrectIn = this.countLogger.addCounter("ao.WNODECORRECT.in");
      this.countMsgWNodeCorrectOut = this.countLogger.addCounter("ao.WNODECORRECT.out");
      this.countMsgMobPathIn = this.countLogger.addCounter("ao.MOB_PATH.in");
      this.countMsgMobPathOut = this.countLogger.addCounter("ao.MOB_PATH.out");
      ContentDatabase ctDB = new ContentDatabase(false);
      String _silenceTimeout = ctDB.loadGameSetting("PLAYER_SILENCE_TIMEOUT");
      if (_silenceTimeout != null) {
         silenceTimeout = Integer.parseInt(_silenceTimeout);
      }

      this.aDB = new AccountDatabase(true);
      this.addProxyExtensionHook("ao.heartbeat", new atavism.server.plugins.ProxyPlugin.PlayerHeartbeat((1)null));
      (new Thread(new atavism.server.plugins.ProxyPlugin.PlayerTimeout(this, (1)null), "PlayerTimeout")).start();
   }

   private static String getPluginName() {
      try {
         String proxyPluginName = Engine.getAgent().getDomainClient().allocName("PLUGIN", "Proxy#");
         return proxyPluginName;
      } catch (IOException var2) {
         throw new AORuntimeException("Could not allocate proxy plugin name", var2);
      }
   }

   public static boolean isOnBlockList(OID subject, OID target) {
      ExtensionMessage message = new ExtensionMessage(SocialClient.MSG_TYPE_IS_ON_BLOCK_LIST, "ao.IS_ON_BLOCK_LIST", subject);
      message.setProperty("targetOid", target);
      return Engine.getAgent().sendRPCReturnBoolean(message);
   }

   public boolean isDevMode() {
      return this.devMode;
   }

   public void setDevMode(boolean mode) {
      this.devMode = mode;
   }

   public List<MessageType> getExtraPlayerMessageTypes() {
      return this.extraPlayerMessageTypes;
   }

   public void setExtraPlayerMessageTypes(List<MessageType> extraPlayerMessageTypes) {
      this.extraPlayerMessageTypes = extraPlayerMessageTypes;
   }

   public void addExtraPlayerMessageType(MessageType messageType) {
      if (this.extraPlayerMessageTypes == null) {
         this.extraPlayerMessageTypes = new LinkedList();
      }

      this.extraPlayerMessageTypes.add(messageType);
   }

   public void addExtraPlayerExtensionMessageType(MessageType messageType) {
      this.addExtraPlayerMessageType(messageType);
      this.getHookManager().addHook(messageType, new atavism.server.plugins.ProxyPlugin.ExtensionHook(this));
   }

   public void addProxyExtensionHook(String subType, ProxyExtensionHook hook) {
      synchronized(this.extensionHooks) {
         List<ProxyExtensionHook> hookList = (List)this.extensionHooks.get(subType);
         if (hookList == null) {
            hookList = new ArrayList();
            this.extensionHooks.put(subType, hookList);
         }

         ((List)hookList).add(hook);
      }
   }

   public Map<String, List<ProxyExtensionHook>> getProxyExtensionHooks(String subType) {
      return this.extensionHooks;
   }

   public void onActivate() {
      try {
         PacketAggregator.initializeAggregation(Engine.getProperties());
         String logProxyHistograms = Engine.properties.getProperty("atavism.log_proxy_histograms");
         if (logProxyHistograms != null && logProxyHistograms.equals("true")) {
            int interval = 5000;
            String intervalString = Engine.properties.getProperty("atavism.log_proxy_histograms_interval");
            if (intervalString != null) {
               int newInterval = Integer.parseInt(intervalString);
               if (newInterval > 0) {
                  interval = newInterval;
               }
            }

            this.proxyQueueHistogram = new TimeHistogram("TimeInQ", interval);
            this.proxyCallbackHistogram = new TimeHistogram("TimeInCallback", interval);
            this.countLogger.start();
         }

         this.filteredProps = new HashSet();
         this.playerSpecificProps = new HashSet();
         this.cachedPlayerSpecificFilterProps = new HashSet();
         this.addFilteredProperty("inv.bag");
         this.addFilteredProperty(":loc");
         this.addFilteredProperty("masterOid");
         this.addFilteredProperty("agisobj.basedc");
         this.addFilteredProperty("aoobj.dc");
         this.addFilteredProperty("aoobj.followsterrainflag");
         this.addFilteredProperty("aoobj.perceiver");
         this.addFilteredProperty("aoobj.scale");
         this.addFilteredProperty("aoobj.mobflag");
         this.addFilteredProperty("aoobj.structflag");
         this.addFilteredProperty("aoobj.userflag");
         this.addFilteredProperty("aoobj.itemflag");
         this.addFilteredProperty("aoobj.lightflag");
         this.addFilteredProperty("namespace");
         this.addFilteredProperty("regenEffectMap");
         this.addFilteredProperty(WorldManagerClient.MOB_PATH_PROPERTY);
         this.addFilteredProperty(WorldManagerClient.TEMPL_SOUND_DATA_LIST);
         this.addFilteredProperty(WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
         this.addFilteredProperty("instanceStack");
         this.addFilteredProperty("currentInstanceName");
         this.addFilteredProperty("ignored_oids");
         this.registerHooks();
         atavism.server.plugins.ProxyPlugin.PluginMessageCallback pluginMessageCallback = new atavism.server.plugins.ProxyPlugin.PluginMessageCallback(this);
         MessageTypeFilter filter = new MessageTypeFilter();
         filter.addType(WorldManagerClient.MSG_TYPE_SYS_CHAT);
         Engine.getAgent().createSubscription(filter, pluginMessageCallback);
         LinkedList<MessageType> types = new LinkedList();
         types.add(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO);
         types.add(WorldManagerClient.MSG_TYPE_ANIMATION);
         types.add(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT);
         types.add(WorldManagerClient.MSG_TYPE_DETACH);
         types.add(PropertyMessage.MSG_TYPE_PROPERTY);
         types.add(ChatClient.MSG_TYPE_COM);
         types.add(SocialClient.MSG_TYPE_BLOCK_LIST);
         types.add(CombatClient.MSG_TYPE_DAMAGE);
         types.add(WorldManagerClient.MSG_TYPE_UPDATEWNODE);
         types.add(WorldManagerClient.MSG_TYPE_MOB_PATH);
         types.add(WorldManagerClient.MSG_TYPE_WNODECORRECT);
         types.add(WorldManagerClient.MSG_TYPE_ORIENT);
         types.add(WorldManagerClient.MSG_TYPE_SOUND);
         types.add(AnimationClient.MSG_TYPE_INVOKE_EFFECT);
         types.add(WorldManagerClient.MSG_TYPE_EXTENSION);
         types.add(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
         types.add(InventoryClient.MSG_TYPE_INV_UPDATE);
         types.add(CombatClient.MSG_TYPE_ABILITY_STATUS);
         types.add(CombatClient.MSG_TYPE_ABILITY_UPDATE);
         types.add(WorldManagerClient.MSG_TYPE_FOG);
         types.add(WorldManagerClient.MSG_TYPE_ROAD);
         types.add(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT);
         types.add(WorldManagerClient.MSG_TYPE_SET_AMBIENT);
         types.add(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY);
         types.add(WorldManagerClient.MSG_TYPE_FREE_OBJECT);
         types.add(MSG_TYPE_VOICE_PARMS);
         types.add(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
         types.add(MSG_TYPE_GET_MATCHING_PLAYERS);
         types.add(MSG_TYPE_ADD_STATIC_PERCEPTION);
         types.add(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
         if (this.extraPlayerMessageTypes != null) {
            types.addAll(this.extraPlayerMessageTypes);
         }

         this.perceptionFilter = new PerceptionFilter(types, true);
         PerceptionTrigger perceptionTrigger = new PerceptionTrigger();
         this.perceptionSubId = Engine.getAgent().createSubscription(this.perceptionFilter, this.playerMessageCallback, 0, perceptionTrigger);
         types.clear();
         types.add(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ);
         types.add(MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
         types.add(MSG_TYPE_GET_PLAYER_LOGIN_STATUS);
         types.add(MSG_TYPE_LOGOUT_PLAYER);
         this.responderFilter = new PerceptionFilter(types);
         this.responderSubId = Engine.getAgent().createSubscription(this.responderFilter, this.playerMessageCallback, 8);
         this.responderFilter2 = new PerceptionFilter();
         this.responderSubId2 = Engine.getAgent().createSubscription(this.responderFilter2, this, 8);
         types.clear();
         types.add(Management.MSG_TYPE_GET_PLUGIN_STATUS);
         Engine.getAgent().createSubscription(new MessageTypeFilter(types), pluginMessageCallback, 8);
         MessageTypeFilter filter3 = new MessageTypeFilter();
         filter3.addType(MSG_TYPE_ACCOUNT_LOGIN);
         Engine.getAgent().createSubscription(filter3, this);
         String log_rdp_counters = Engine.getProperty("atavism.log_rdp_counters");
         if (log_rdp_counters == null || log_rdp_counters.equals("false")) {
            RDPServer.setCounterLogging(false);
         }

         RDPServer.startRDPServer();
         this.initializeVoiceServerInformation();
         this.registerExtensionSubtype("voice_parms", MSG_TYPE_VOICE_PARMS);
         this.registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
         this.registerExtensionSubtype("player_path_req", MSG_TYPE_PLAYER_PATH_REQ);
         this.registerExtensionSubtype("ao.UPDATE_PLAYER_IGNORE_LIST", MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST);
         this.registerExtensionSubtype("ao.GET_MATCHING_PLAYERS", MSG_TYPE_GET_MATCHING_PLAYERS);
         this.registerExtensionSubtype("ao.PLAYER_IGNORE_LIST_REQ", MSG_TYPE_PLAYER_IGNORE_LIST_REQ);
         Log.debug("ProxyPlugin before bindAddress");
         InetSocketAddress bindAddress = this.getBindAddress();
         Log.debug("ProxyPlugin after bindAddress " + bindAddress.getHostName() + " " + bindAddress.getAddress() + " " + bindAddress.getPort());
         Log.debug("ProxyPlugin before server socket");
         int port = Integer.parseInt(Engine.getProperty("atavism.proxy.bindport").trim());
         Log.debug("Proxy: getBindAddress port=" + port);
         String agent_name = Engine.getAgent().getName();
         String[] an = agent_name.split("_");
         int agentId = Integer.parseInt(an[1]);
         port += agentId - 1;
         int rdpChannels = Integer.parseInt(Engine.properties.getProperty("atavism.proxy.rdp_channels", String.valueOf(128)));

         for(int i = 0; i < rdpChannels; ++i) {
            RDPServerSocket serverSocket = new RDPServerSocket();
            serverSocket.registerAcceptCallback(this);
            serverSocket.bind(port, serverSocketReceiveBufferSize);
            if (Log.loggingDebug) {
               Log.debug("BIND: binding for client tcp and rdp packets on port " + bindAddress.getPort() + " with rdpsocket: " + serverSocket.toString());
            }
         }

         Log.debug("BIND: bound server socket");
         this.clientTCPMessageIO = ClientTCPMessageIO.setup(bindAddress, this, this);
         Log.debug("BIND: setup clientTCPMessage");
         this.clientTCPMessageIO.start("ClientIO");
         Log.debug("BIND: started clientTCPMessage");
         InetSocketAddress externalAddress = this.getExternalAddress(bindAddress);
         Log.debug("BIND: got external Address " + externalAddress.getHostName() + " " + externalAddress.getAddress() + " " + externalAddress.getPort());
         this.setPluginInfo("host=" + Engine.getProperty("atavism.proxy.externaladdress") + ",port=" + externalAddress.getPort());
         Log.debug("Registering proxy plugin");
         Engine.registerStatusReportingPlugin(this);
         Log.debug("Proxy: activation done");
         this.runCheck();
         Gauge.builder("event_qq_size", new 1(this)).register(Prometheus.registry());
         Gauge.builder("message_qq_size", new 2(this)).register(Prometheus.registry());
         Gauge.builder("message_qq_unqueued_size", new 3(this)).register(Prometheus.registry());
      } catch (Exception var16) {
         throw new AORuntimeException("activate failed", var16);
      }
   }

   private InetSocketAddress getBindAddress() throws IOException {
      String propStr = Engine.getProperty("atavism.proxy.bindport");
      Log.debug("Proxy: getBindAddress propStr=" + propStr);
      int port;
      if (propStr != null) {
         port = Integer.parseInt(propStr.trim());
         Log.debug("Proxy: getBindAddress port=" + port);
         String agent_name = Engine.getAgent().getName();
         String[] an = agent_name.split("_");
         int agentId = Integer.parseInt(an[1]);
         port += agentId - 1;
         Log.debug("Proxy: getBindAddress port=" + port);
      } else {
         port = Integer.parseInt(Engine.getProperty("atavism.proxyport").trim());
      }

      Log.debug("Proxy: getBindAddress port=" + port);
      propStr = Engine.getProperty("atavism.proxy.bindaddress");
      Log.debug("Proxy: getBindAddress propStr=" + propStr + " " + Character.digit(propStr.charAt(0), 16) + " " + Character.digit(propStr.charAt(1), 16) + " " + Character.digit(propStr.charAt(2), 16) + " c=");
      int count = 0;
      if (propStr.contains(".")) {
         for(int i = 0; i < propStr.length(); ++i) {
            if (propStr.charAt(i) == '.') {
               ++count;
            }
         }
      }

      InetAddress address = null;
      InetAddress[] address2 = null;
      if (count == 3 && Character.digit(propStr.charAt(0), 10) != -1) {
      }

      if (propStr != null) {
         try {
            address = InetAddress.getByName(propStr.trim());
            address2 = InetAddress.getAllByName(propStr.trim());
            InetAddress[] var6 = address2;
            int var7 = address2.length;

            for(int var8 = 0; var8 < var7; ++var8) {
               InetAddress ai = var6[var8];
               Log.debug("Proxy: getBindAddress address2=" + ai + " " + ai.getHostName() + " " + ai.getHostAddress());
            }

            Log.debug("Proxy: getBindAddress address=" + address + " " + address.getHostName() + " " + address.getHostAddress());
         } catch (UnknownHostException var10) {
            log.error("getBindAddress " + var10.getMessage() + " " + var10.getLocalizedMessage());
         }
      }

      Log.debug("Proxy: getBindAddress address=" + address + " " + address.getHostName() + " " + address.getAddress());
      return new InetSocketAddress(address, port);
   }

   private InetSocketAddress getExternalAddress(InetSocketAddress bindAddress) throws IOException {
      String propStr = Engine.getProperty("atavism.proxy.externalport");
      Log.debug("Proxy: getExternalAddress ext port propStr=" + propStr);
      int port;
      if (propStr != null) {
         port = Integer.parseInt(propStr.trim());
      } else {
         port = bindAddress.getPort();
      }

      Log.debug("Proxy: getExternalAddress port=" + port);
      propStr = Engine.getProperty("atavism.proxy.externaladdress");
      Log.debug("Proxy: getExternalAddress ext addr propStr=" + propStr);
      InetAddress address;
      if (propStr != null) {
         address = InetAddress.getByName(propStr.trim());
      } else {
         address = bindAddress.getAddress();
         Log.debug("Proxy: getExternalAddress else address=" + address);
         if (address.isAnyLocalAddress()) {
            address = InetAddress.getLocalHost();
            Log.debug("Proxy: getExternalAddress get local host address=" + address + " " + address.getHostName() + " " + address.getHostAddress());
         }
      }

      Log.debug("Proxy: getExternalAddress address=" + address + " " + address.getHostName() + " " + address.getAddress());
      return new InetSocketAddress(address, port);
   }

   private String howla() {
      String characters = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijklmnoprstquwxyz123456789";
      String k = "";

      for(int i = 0; i < 14; ++i) {
         Random random = new Random();
         k = k + characters.charAt(random.nextInt(characters.length() - 1));
      }

      return k;
   }

   private void runCheck() {
      String email = Engine.getProperty("atavism.licence.email");
      String licencekey = Engine.getProperty("atavism.licence.key");
      String proxy_id = Engine.getProperty("atavism.proxy.id");
      int num = 0;
      int proxyId = 0;

      try {
         if (proxy_id != null && proxy_id != "") {
            proxyId = Integer.parseInt(proxy_id);
         }
      } catch (NumberFormatException var18) {
      }

      String[] url = new String[]{"https://apanel.atavismonline.com/login/verifyserver.php", "https://licensing2.dragonsan.com:2443/login/verifyserver.php", "https://licensing1.atavismonline.com/login/verifyserver.php", "https://licensing.dragonsan.com/login/verifyserver.php", "https://licensing1.dragonsan.com/login/verifyserver.php", "https://licensing.atavismonline.com/login/verifyserver.php", "https://licensing2.atavismonline.com/login/verifyserver.php"};
      String resSor = this.howla();
      atavism.server.plugins.ProxyPlugin.rck reCheck = new atavism.server.plugins.ProxyPlugin.rck(this, resSor);
      Engine.getExecutor().scheduleAtFixedRate(reCheck, 300L, 300L, TimeUnit.SECONDS);

      while(num < url.length) {
         boolean failed = false;

         try {
            String res = "";
            URL urlObj = new URL(url[num]);
            URLConnection lu = urlObj.openConnection();
            lu.setConnectTimeout(10000);
            String data = "email=" + URLEncoder.encode(email, "UTF-8") + "&licence=" + URLEncoder.encode(licencekey, "UTF-8") + "&ver=" + URLEncoder.encode("10.7.0", "UTF-8") + "&addr=" + URLEncoder.encode(Engine.getProperty("atavism.proxy.bindaddress"), "UTF-8") + "&sor=" + URLEncoder.encode(resSor, "UTF-8") + "&c=" + URLEncoder.encode("0", "UTF-8") + "&cp=" + this.playerManager.getPlayerCount() + " &pi=" + proxyId + "&build=" + URLEncoder.encode(ServerVersion.getBuildDate(), "UTF-8") + "&m=" + MaxConcurrentUsers;
            lu.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(lu.getOutputStream());
            wr.write(data);
            wr.flush();
            BufferedReader rd = new BufferedReader(new InputStreamReader(lu.getInputStream()));

            for(String line = ""; (line = rd.readLine()) != null; res = res + line) {
            }

            wr.flush();
            wr.close();
            if (debugLic) {
               System.out.println("\n" + url[num] + "\n" + res + "\n");
            }

            res = HelperFunctions.readEncodedString(Base64.decode(res));
            String[] output = res.split(":");
            if (debugLic) {
               System.out.println("\nsec: " + resSor + "\n s: " + HelperFunctions.readEncodedString(Base64.decode(output[2])) + "\n");
            }

            if (EncryptionHelper.passwordMD5Check(output[0], this.getTemp()) && resSor.equals(HelperFunctions.readEncodedString(Base64.decode(output[2])))) {
               this.connectionLimit = Integer.parseInt(HelperFunctions.readEncodedString(Base64.decode(output[1])));
            } else {
               System.out.println("\nLicense verification failed");
               Log.error("License verification failed");
            }

            Log.debug("CONNECTOR: connections set to: " + this.connectionLimit);
         } catch (Exception var19) {
            Log.error("CONNECTOR: failed verifying " + var19);
            if (debugLic) {
               System.out.println("\n" + url[num] + "\n" + var19);
            }

            ++num;
            failed = true;
         }

         if (!failed) {
            return;
         }
      }

      System.out.println("\nLicense verification failed");
      Log.error("License verification failed");
      this.connectionLimit = 0;
   }

   public Map<String, String> getStatusMap() {
      Map<String, String> status = new HashMap();
      status.put("players", Integer.toString(this.playerManager.getPlayerCount()));
      return status;
   }

   public void registerCommand(String command, atavism.server.plugins.ProxyPlugin.CommandParser parser) {
      this.commandMapLock.lock();

      try {
         this.commandMap.put(command, new atavism.server.plugins.ProxyPlugin.RegisteredCommand(parser, this.defaultCommandAccess));
      } finally {
         this.commandMapLock.unlock();
      }

   }

   public void registerCommand(String command, atavism.server.plugins.ProxyPlugin.CommandParser parser, atavism.server.plugins.ProxyPlugin.CommandAccessCheck access) {
      this.commandMapLock.lock();

      try {
         this.commandMap.put(command, new atavism.server.plugins.ProxyPlugin.RegisteredCommand(parser, access));
      } finally {
         this.commandMapLock.unlock();
      }

   }

   void registerHooks() {
      log.debug("registering hooks");
      this.getHookManager().addHook(SocialClient.MSG_TYPE_BLOCK_LIST, new atavism.server.plugins.ProxyPlugin.BlockListHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_DISPLAY_CONTEXT, new atavism.server.plugins.ProxyPlugin.DisplayContextHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_DETACH, new atavism.server.plugins.ProxyPlugin.DetachHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_ANIMATION, new atavism.server.plugins.ProxyPlugin.AnimationHook(this));
      this.getHookManager().addHook(AnimationClient.MSG_TYPE_INVOKE_EFFECT, new atavism.server.plugins.ProxyPlugin.InvokeEffectHook(this));
      this.getHookManager().addHook(PropertyMessage.MSG_TYPE_PROPERTY, new atavism.server.plugins.ProxyPlugin.PropertyHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_EXTENSION, new atavism.server.plugins.ProxyPlugin.ExtensionHook(this));
      this.getHookManager().addHook(CombatClient.MSG_TYPE_ABILITY_STATUS, new atavism.server.plugins.ProxyPlugin.AbilityStatusHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_TARGETED_PROPERTY, new atavism.server.plugins.ProxyPlugin.TargetedPropertyHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_PERCEPTION_INFO, new atavism.server.plugins.ProxyPlugin.PerceptionHook(this));
      this.getHookManager().addHook(ChatClient.MSG_TYPE_COM, new atavism.server.plugins.ProxyPlugin.ComHook(this));
      this.getHookManager().addHook(CombatClient.MSG_TYPE_DAMAGE, new atavism.server.plugins.ProxyPlugin.DamageHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_SYS_CHAT, new atavism.server.plugins.ProxyPlugin.SysChatHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_UPDATEWNODE, new atavism.server.plugins.ProxyPlugin.UpdateWNodeHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_MOB_PATH, new atavism.server.plugins.ProxyPlugin.UpdateMobPathHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_WNODECORRECT, new atavism.server.plugins.ProxyPlugin.WNodeCorrectHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_ORIENT, new atavism.server.plugins.ProxyPlugin.OrientHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_SOUND, new atavism.server.plugins.ProxyPlugin.SoundHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_FOG, new atavism.server.plugins.ProxyPlugin.FogHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_ROAD, new atavism.server.plugins.ProxyPlugin.RoadHook(this));
      this.getHookManager().addHook(InventoryClient.MSG_TYPE_INV_UPDATE, new atavism.server.plugins.ProxyPlugin.InvUpdateHook(this));
      this.getHookManager().addHook(CombatClient.MSG_TYPE_ABILITY_UPDATE, new atavism.server.plugins.ProxyPlugin.AbilityUpdateHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_NEW_DIRLIGHT, new atavism.server.plugins.ProxyPlugin.NewDirLightHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_FREE_OBJECT, new atavism.server.plugins.ProxyPlugin.FreeObjectHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_SET_AMBIENT, new atavism.server.plugins.ProxyPlugin.SetAmbientHook(this));
      this.getHookManager().addHook(WorldManagerClient.MSG_TYPE_P2P_EXTENSION, new atavism.server.plugins.ProxyPlugin.P2PExtensionHook(this));
      this.getHookManager().addHook(MSG_TYPE_VOICE_PARMS, new atavism.server.plugins.ProxyPlugin.VoiceParmsHook(this));
      this.getHookManager().addHook(MSG_TYPE_PLAYER_PATH_REQ, new atavism.server.plugins.ProxyPlugin.PlayerPathReqHook(this));
      this.getHookManager().addHook(InstanceClient.MSG_TYPE_INSTANCE_ENTRY_REQ, new atavism.server.plugins.ProxyPlugin.InstanceEntryReqHook(this));
      this.getHookManager().addHook(Management.MSG_TYPE_GET_PLUGIN_STATUS, new atavism.server.plugins.ProxyPlugin.GetPluginStatusHook(this));
      this.getHookManager().addHook(MSG_TYPE_UPDATE_PLAYER_IGNORE_LIST, new atavism.server.plugins.ProxyPlugin.UpdatePlayerIgnoreListHook(this));
      this.getHookManager().addHook(MSG_TYPE_GET_MATCHING_PLAYERS, new atavism.server.plugins.ProxyPlugin.GetMatchingPlayersHook(this));
      this.getHookManager().addHook(MSG_TYPE_PLAYER_IGNORE_LIST_REQ, new atavism.server.plugins.ProxyPlugin.PlayerIgnoreListReqHook(this));
      this.getHookManager().addHook(MSG_TYPE_GET_PLAYER_LOGIN_STATUS, new atavism.server.plugins.ProxyPlugin.GetPlayerLoginStatusHook(this, (1)null));
      this.getHookManager().addHook(MSG_TYPE_LOGOUT_PLAYER, new atavism.server.plugins.ProxyPlugin.LogoutPlayerHook(this, (1)null));
      this.getHookManager().addHook(MSG_TYPE_ADD_STATIC_PERCEPTION, new atavism.server.plugins.ProxyPlugin.AddStaticPerceptionHook(this, (1)null));
      this.getHookManager().addHook(MSG_TYPE_REMOVE_STATIC_PERCEPTION, new atavism.server.plugins.ProxyPlugin.RemoveStaticPerceptionHook(this, (1)null));
      this.getHookManager().addHook(MSG_TYPE_ACCOUNT_LOGIN, new atavism.server.plugins.ProxyPlugin.AccountLoginHook(this, (1)null));
   }

   void callEngineOnMessage(Message message, int flags) {
      super.handleMessage(message, flags);
   }

   protected void initializeVoiceServerInformation() {
      voiceServerHost = Engine.properties.getProperty("atavism.voiceserver");
      String s = Engine.properties.getProperty("atavism.voiceport");
      if (s != null) {
         voiceServerPort = Integer.parseInt(s);
      }

      if (Log.loggingDebug) {
         log.debug("initializeVoiceServerInformation: voiceServerHost " + voiceServerHost + ", voiceServerPort " + voiceServerPort);
      }

   }

   public void acceptConnection(ClientConnection con) {
      Log.info("ProxyPlugin: CONNECTION remote=" + con);
      con.registerMessageCallback(this);
   }

   public void processPacket(ClientConnection con, AOByteBuffer buf) {
      try {
         long time1 = System.nanoTime();
         if (Log.loggingNet) {
            if (ClientConnection.getLogMessageContents()) {
               Log.net("ProxyPlugin.processPacket: con " + con + ", length " + buf.limit() + ", packet " + DebugUtils.byteArrayToHexString(buf));
            } else {
               Log.net("ProxyPlugin.processPacket: con " + con + ", buf " + buf);
            }
         }

         Event event = Engine.getEventServer().parseBytes(buf, con);
         if (event == null) {
            Log.error("Engine: could not parse packet data, remote=" + con);
            return;
         }

         SquareQueue<Player, Event> qq = this.eventQQ;
         if (event instanceof AuthorizedLoginEvent) {
            qq = this.slowEventQQ;
         }

         Player player = (Player)con.getAssociation();
         if (player == null) {
            if (!(event instanceof AuthorizedLoginEvent)) {
               Log.error("Cannot process event for connection with no player: " + con);
               return;
            }

            Log.info("ProxyPlugin: LOGIN_RECV remote=" + con + " playerOid=" + ((AuthorizedLoginEvent)event).getOid());
            player = new Player(((AuthorizedLoginEvent)event).getOid(), con);
         }

         this.playerManager.processEvent(player, event, qq);
         long time2 = System.nanoTime();
         Timer.builder("process_packet_time").tags(new String[]{"event", event.getClass().getSimpleName()}).publishPercentiles(new double[]{0.9D}).register(Prometheus.registry()).record(Duration.ofNanos(time2 - time1));
      } catch (AORuntimeException var10) {
         Log.exception("ProxyPlugin.processPacket caught exception", var10);
      }

   }

   public Set<OID> getPlayerOids() {
      List<Player> players = new ArrayList(this.playerManager.getPlayerCount());
      this.playerManager.getPlayers(players);
      Set<OID> result = new HashSet(players.size());
      Iterator var3 = players.iterator();

      while(var3.hasNext()) {
         Player player = (Player)var3.next();
         result.add(player.getOid());
      }

      return result;
   }

   public List<String> getPlayerNames() {
      List<Player> players = new ArrayList(this.playerManager.getPlayerCount());
      Log.debug("ProxyPlugin.getPlayerNames: count is " + this.playerManager.getPlayerCount());
      this.playerManager.getPlayers(players);
      List<String> result = new ArrayList(players.size());
      Iterator var3 = players.iterator();

      while(var3.hasNext()) {
         Player player = (Player)var3.next();
         result.add(player.getName() + " " + player.getOid() + " " + this.getName());
      }

      Collections.sort(result);
      return result;
   }

   public List<String> getAllPlayerNames() {
      Log.debug("ProxyPlugin.getAllPlayerNames: count is " + this.playersOnlineList.size());
      List<String> result = new ArrayList(this.playersOnlineList.size());
      HashMap<OID, String> plays = new HashMap();
      plays.putAll(this.playersOnlineList);
      Iterator var3 = plays.keySet().iterator();

      while(var3.hasNext()) {
         OID player = (OID)var3.next();
         result.add((String)plays.get(player) + " " + player + " " + (String)this.playersOnlineOnProxy.get(player));
      }

      Collections.sort(result);
      return result;
   }

   public List<Player> getPlayers() {
      List<Player> players = new ArrayList(this.playerManager.getPlayerCount());
      this.playerManager.getPlayers(players);
      return players;
   }

   public Player getPlayer(OID oid) {
      return this.playerManager.getPlayer(oid);
   }

   public void addPlayerMessage(Message message, Player player) {
      long start = System.nanoTime();
      message.setEnqueueTime();
      this.messageQQ.insert(player, message);
      long microseconds = System.nanoTime() - start;
   }

   public void addFilteredProperty(String filteredProperty) {
      this.filteredProps.add(filteredProperty);
      this.cachedPlayerSpecificFilterProps.add(filteredProperty);
   }

   public void addPlayerSpecificProperty(String filteredProperty) {
      this.playerSpecificProps.add(filteredProperty);
      this.cachedPlayerSpecificFilterProps.add(filteredProperty);
   }

   protected void recreatePlayerSpecificCache() {
      this.cachedPlayerSpecificFilterProps = new HashSet();
      this.cachedPlayerSpecificFilterProps.addAll(this.filteredProps);
      this.cachedPlayerSpecificFilterProps.addAll(this.playerSpecificProps);
   }

   protected boolean processLogin(ClientConnection con, AuthorizedLoginEvent loginEvent) {
      Prometheus.registry().counter("player_login_request", new String[0]).increment();
      OID playerOid = loginEvent.getOid();
      String version = loginEvent.getVersion();
      int nPlayers = this.playerManager.getPlayerCount();
      String[] clientVersionCapabilities = null;
      if (version != null && version.length() > 0) {
         clientVersionCapabilities = version.split(",");
      }

      LinkedList<String> clientCapabilities = new LinkedList();
      String clientVersion = "";
      int i;
      if (clientVersionCapabilities != null && clientVersionCapabilities.length > 0) {
         clientVersion = clientVersionCapabilities[0];

         for(i = 1; i < clientVersionCapabilities.length; ++i) {
            clientCapabilities.add(clientVersionCapabilities[i].trim());
         }
      }

      i = ServerVersion.compareVersionStrings(clientVersion, "10.7.0");
      AuthorizedLoginResponseEvent loginResponse;
      if (i != 0) {
         Log.warn("processLogin: unsupported version " + clientVersion + " from player: " + playerOid);
         loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Unsupported client version", this.serverVersion);
         con.send(loginResponse.toBytes());
         Prometheus.registry().counter("player_login_result", new String[]{"status", "unsupported_version"}).increment();
         return false;
      } else {
         if (this.isAdmin(playerOid) && nPlayers < this.connectionLimit) {
            Log.debug("processLogin: player is admin, bypassing max check");
         } else {
            Log.debug("processLogin: player is not admin");
            if (nPlayers >= MaxConcurrentUsers || nPlayers >= this.connectionLimit) {
               Log.warn("processLogin: too many users, failed for player: " + playerOid);
               loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, this.capacityError, this.serverVersion);
               con.send(loginResponse.toBytes());
               Prometheus.registry().counter("player_login_result", new String[]{"status", "too_many_users_" + String.valueOf(this.connectionLimit)}).increment();
               return false;
            }
         }

         SecureToken token = SecureTokenManager.getInstance().importToken(loginEvent.getWorldToken());
         boolean validToken = true;
         if (!token.getValid()) {
            Log.debug("token is not valid");
            validToken = false;
         }

         OID characterOid = (OID)token.getProperty("character_oid");
         if (Log.loggingDebug) {
            Log.debug("PlayerOID: " + playerOid);
         }

         if (Log.loggingDebug) {
            Log.debug("CharacterOID: " + characterOid);
         }

         if (!playerOid.equals(characterOid)) {
            Log.debug("playerOid does not match character_oid");
            validToken = false;
         }

         if (!token.getProperty("proxy_server").equals(Engine.getAgent().getName())) {
            Log.debug("proxy_server does not match engine agent name");
            validToken = false;
         }

         if (!validToken) {
            Log.error("processLogin: invalid proxy token");
            Event loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, this.tokenError, this.serverVersion);
            con.send(loginResponse.toBytes());
            Prometheus.registry().counter("player_login_result", new String[]{"status", "invalid_token"}).increment();
            return false;
         } else {
            try {
               TargetMessage getPlayerLoginStatus = new TargetMessage(MSG_TYPE_GET_PLAYER_LOGIN_STATUS, playerOid);
               atavism.server.plugins.ProxyPlugin.PlayerLoginStatus loginStatus = (atavism.server.plugins.ProxyPlugin.PlayerLoginStatus)Engine.getAgent().sendRPCReturnObject(getPlayerLoginStatus);
               if (this.proxyLoginCallback.duplicateLogin(loginStatus, con)) {
                  if (loginStatus != null) {
                     if (Log.loggingInfo) {
                        Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " name=" + loginStatus.name + " existingCon=" + loginStatus.clientCon + " existingProxy=" + loginStatus.proxyPluginName);
                     }
                  } else if (Log.loggingInfo) {
                     Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " loginStatus is null");
                  }

                  log.debug("processLogin: Send logout");
                  Prometheus.registry().counter("player_logout", new String[]{"reason", "duplicate"}).increment();
                  TargetMessage logoutPly = new TargetMessage(MSG_TYPE_LOGOUT_PLAYER, playerOid);
                  Engine.getAgent().sendRPCReturnObject(logoutPly);
                  log.debug("processLogin: Send logout | ");
                  AuthorizedLoginResponseEvent loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Already connected", this.serverVersion);
                  con.send(loginResponse.toBytes());
                  Prometheus.registry().counter("player_login_result", new String[]{"status", "duplicate"}).increment();
                  return false;
               }
            } catch (NoRecipientsException var20) {
               if (Log.loggingDebug) {
                  log.debug("processLogin: OK! player is not logged " + var20);
               }
            }

            Player player = new Player(playerOid, con);
            player.setStatus(1);
            if (!this.playerManager.addPlayer(player)) {
               player = this.playerManager.getPlayer(playerOid);
               Log.info("processLogin: LOGIN_DUPLICATE remote=" + con + " playerOid=" + playerOid + " existing=" + player.getConnection());
               AuthorizedLoginResponseEvent loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed: Already connected", this.serverVersion);
               con.send(loginResponse.toBytes());
               Prometheus.registry().counter("player_login_result", new String[]{"status", "duplicate_add"}).increment();
               return false;
            } else {
               con.setAssociation(player);
               player.setVersion(clientVersion);
               player.setCapabilities(clientCapabilities);
               String errorMessage = this.proxyLoginCallback.preLoad(player, con);
               AuthorizedLoginResponseEvent loginResponse;
               if (errorMessage != null) {
                  this.playerManager.removePlayer(playerOid);
                  loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, errorMessage, this.serverVersion);
                  con.send(loginResponse.toBytes());
                  Prometheus.registry().counter("player_login_result", new String[]{"status", "pre_load_error"}).increment();
                  return false;
               } else {
                  if (Log.loggingDebug) {
                     Log.debug("processLogin: loading object: " + playerOid + ", con=" + con);
                  }

                  if (!this.loadPlayerObject(player)) {
                     Log.error("processLogin: could not load object " + playerOid);
                     this.playerManager.removePlayer(playerOid);
                     loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, "Login Failed", this.serverVersion);
                     con.send(loginResponse.toBytes());
                     Prometheus.registry().counter("player_login_result", new String[]{"status", "not_loaded"}).increment();
                     return false;
                  } else {
                     if (Log.loggingDebug) {
                        Log.debug("processLogin: loaded player object: " + playerOid);
                     }

                     errorMessage = this.proxyLoginCallback.postLoad(player, con);
                     if (errorMessage != null) {
                        this.playerManager.removePlayer(playerOid);
                        loginResponse = new AuthorizedLoginResponseEvent(playerOid, false, errorMessage, this.serverVersion);
                        con.send(loginResponse.toBytes());
                        Prometheus.registry().counter("player_login_result", new String[]{"status", "error"}).increment();
                        return false;
                     } else {
                        loginResponse = new AuthorizedLoginResponseEvent(playerOid, true, "Login Succeeded", this.serverVersion + ", " + this.serverCapabilitiesSentToClient);
                        con.send(loginResponse.toBytes());
                        if (Log.loggingDebug) {
                           Log.debug("Login response sent for playerOid=" + playerOid + " the authorized login response message is : " + loginResponse.getMessage());
                        }

                        this.playerManager.addStaticPerception(player, playerOid);
                        boolean loginOK = this.processLoginHelper(con, player);
                        if (Log.loggingDebug) {
                           log.debug("processLogin: loginOK?:" + loginOK + "  | player=" + player);
                        }

                        if (!loginOK) {
                           if (Log.loggingDebug) {
                              Log.debug("processLogin: loading object: " + playerOid + ", con=" + con + " login failed disconect player");
                           }

                           con.setAssociation((Object)null);
                           if (this.perceptionFilter.removeTarget(playerOid)) {
                              FilterUpdate filterUpdate = new FilterUpdate(1);
                              filterUpdate.removeFieldValue(1, playerOid);
                              Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
                              this.responderFilter.removeTarget(playerOid);
                              this.responderFilter2.removeTarget(playerOid);
                              Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
                              Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
                           }

                           this.playerManager.removeStaticPerception(player, playerOid);
                           this.playerManager.removePlayer(playerOid);
                           Prometheus.registry().counter("rdp_connection_closed", new String[]{"reason", "bad_login"}).increment();
                           con.close();
                        } else {
                           this.proxyLoginCallback.postSpawn(player, con);
                           this.playerManager.loginComplete(player, this.eventQQ);
                           SubjectMessage loginSpawned = new SubjectMessage(MSG_TYPE_LOGIN_SPAWNED);
                           loginSpawned.setSubject(playerOid);
                           Engine.getAgent().sendBroadcast(loginSpawned);
                           this.processPlayerIgnoreList(player);
                           OID accountID = (OID)EnginePlugin.getObjectProperty(playerOid, WorldManagerClient.NAMESPACE, "accountId");
                           this.clientConnections.put(accountID, con);
                           if (player.getStatus() == 3) {
                              atavism.server.plugins.ProxyPlugin.ConnectionResetMessage message = new atavism.server.plugins.ProxyPlugin.ConnectionResetMessage(this, con, player);
                              message.setEnqueueTime();
                              this.messageQQ.insert(player, message);
                           }
                        }

                        Prometheus.registry().counter("player_login_result", new String[]{"status", loginOK ? "ok" : "failed"}).increment();
                        if (Log.loggingDebug) {
                           log.debug("processLogin: loginOK?:" + loginOK + " || player=" + player);
                           log.debug("processLogin: loginOK:" + loginOK + " end");
                        }

                        return loginOK;
                     }
                  }
               }
            }
         }
      }
   }

   protected boolean loadPlayerObject(Player player) {
      if (Log.loggingDebug) {
         log.debug("loadPlayerObject player " + player);
      }

      InstanceRestorePoint restorePoint = null;
      LinkedList restoreStack = null;
      boolean first = true;
      OID playerOid = player.getOid();
      List<Namespace> namespaces = new ArrayList();
      OID oidResult = ObjectManagerClient.loadSubObject(playerOid, namespaces);
      if (Log.loggingDebug) {
         log.debug("loadPlayerObject player " + player + " oidResult=" + oidResult);
      }

      if (oidResult == null) {
         return false;
      } else {
         Point location = new Point();
         OID instanceOid = Engine.getDatabase().getLocation(playerOid, WorldManagerClient.NAMESPACE, location);
         if (Log.loggingDebug) {
            log.debug("loadPlayerObject instanceOid " + instanceOid + " instanceEntryAllowed:" + this.instanceEntryAllowed(playerOid, instanceOid, location));
         }

         if (Log.loggingDebug) {
            log.debug("loadPlayerObject: trying to load player into instance: " + instanceOid);
         }

         int guildID = this.aDB.GetGuildId(playerOid);
         if (Log.loggingDebug) {
            log.debug("loadPlayerObject: load player guildID: " + guildID);
         }

         while(true) {
            try {
               OID result = null;
               if (this.instanceEntryAllowed(playerOid, instanceOid, location)) {
                  InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145);
                  if (Log.loggingDebug) {
                     log.debug("loadPlayerObject InstanceInfo " + instanceInfo + " plyOid=" + instanceInfo.playerOid + " tempId" + instanceInfo.templateID + " groupId" + instanceInfo.groupOid + " guildId" + instanceInfo.guildId + " start do ");
                  }

                  if (instanceInfo.oid != null && (instanceInfo.populationLimit < 1 || instanceInfo.playerPopulation < instanceInfo.populationLimit)) {
                     result = ObjectManagerClient.loadObject(playerOid);
                     if (Log.loggingDebug) {
                        Log.debug("loadPlayerObject: loading player into instance: " + instanceInfo.oid + " of ID: " + instanceInfo.templateID);
                     }
                  }
               }

               if (restoreStack != null && !restorePoint.getFallbackFlag()) {
                  EnginePlugin.setObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack", restoreStack);
               }

               if (result == null) {
                  if (first) {
                     Integer instanceID = (Integer)EnginePlugin.getObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "currentInstanceName");
                     if (Log.loggingDebug) {
                        log.debug("Failed initial load, retrying with current instanceID=" + instanceID);
                     }

                     if (Log.loggingDebug) {
                        log.debug(" loadPlayerObject instanceID=" + instanceID + "  playerOid=" + playerOid + " guildID=" + guildID);
                     }

                     if (instanceID > 0) {
                        instanceOid = this.instanceEntryCallback.selectInstance(player, instanceID, playerOid, guildID);
                        if (Log.loggingDebug) {
                           log.debug("loadPlayerObject instanceOid:" + instanceOid);
                        }

                        if (instanceOid != null) {
                           InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145, false);
                           if (Log.loggingDebug) {
                              log.debug(" loadPlayerObject InstanceInfo " + instanceInfo + " plyOid=" + instanceInfo.playerOid + " tempId=" + instanceInfo.templateID + " groupId=" + instanceInfo.groupOid + " guildId=" + instanceInfo.guildId);
                           }

                           if (instanceInfo.oid != null) {
                              if (instanceInfo.populationLimit > 0 && instanceInfo.playerPopulation >= instanceInfo.populationLimit) {
                                 if (Log.loggingDebug) {
                                    Log.debug("POP: got population: " + instanceInfo.playerPopulation + " and limit: " + instanceInfo.populationLimit);
                                 }

                                 instanceOid = handleFullInstance(instanceInfo.templateID, instanceInfo);
                                 instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145);
                                 log.debug(" loadPlayerObject 2 InstanceInfo " + instanceInfo + " plyOid" + instanceInfo.playerOid + " tempId=" + instanceInfo.templateID + " groupId=" + instanceInfo.groupOid + " guildId=" + instanceInfo.guildId);
                              }

                              if (Log.loggingDebug) {
                                 log.debug("Failed initial load, retrying with instanceOid=" + instanceOid + " and instanceName: " + instanceInfo.name);
                              }

                              BasicWorldNode wnode = new BasicWorldNode();
                              wnode.setInstanceOid(instanceOid);
                              ObjectManagerClient.fixWorldNode(playerOid, wnode);
                              first = false;
                              continue;
                           }
                        }
                     }
                  }

                  if (restorePoint != null && restorePoint.getFallbackFlag()) {
                     if (Log.loggingDebug) {
                        log.debug("loadPlayerObject instanceOid " + instanceOid + " restorePoint:" + restorePoint + " restorePoint.getFallbackFlag():" + restorePoint.getFallbackFlag() + " return false");
                     }

                     return false;
                  }

                  restoreStack = (LinkedList)EnginePlugin.getObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack");
                  if (restoreStack != null && restoreStack.size() != 0) {
                     int size = restoreStack.size();
                     restorePoint = (InstanceRestorePoint)restoreStack.get(size - 1);
                     instanceOid = restorePoint.getInstanceOid();
                     if (restorePoint.getInstanceID() > 0) {
                        instanceOid = this.instanceEntryCallback.selectInstance(player, restorePoint.getInstanceID());
                        if (Log.loggingDebug) {
                           Log.debug("Failed finding matching instance, retrying with restore point instanceID=" + restorePoint.getInstanceID() + " result: " + instanceOid);
                        }
                     }

                     if (instanceOid != null) {
                        BasicWorldNode wnode = new BasicWorldNode();
                        wnode.setInstanceOid(instanceOid);
                        wnode.setLoc(restorePoint.getLoc());
                        wnode.setOrientation(restorePoint.getOrientation());
                        wnode.setDir(new AOVector(0.0F, 0.0F, 0.0F));
                        boolean rc = ObjectManagerClient.fixWorldNode(playerOid, wnode);
                        if (!rc) {
                           if (Log.loggingDebug) {
                              log.debug("loadPlayerObject instanceOid " + instanceOid + " rc:" + rc + " return false");
                           }

                           return false;
                        }

                        location = restorePoint.getLoc();
                     }

                     first = false;
                     if (!restorePoint.getFallbackFlag()) {
                        restoreStack.remove(size - 1);
                     }
                     continue;
                  }

                  Log.error("Failed finding matching instance, and restore stack is null or empty?" + restoreStack + " return false");
                  return false;
               }

               if (restorePoint != null) {
                  EnginePlugin.setObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "currentInstanceName", restorePoint.getInstanceID());
                  if (Log.loggingDebug) {
                     log.debug("INSTANCE: setting current instance prop: " + restorePoint.getInstanceID());
                  }
               }
            } catch (Exception var15) {
               log.error("loadPlayerObject instanceOid " + instanceOid + " Exception: " + var15.getMessage() + " " + var15.getLocalizedMessage());
            }

            if (Log.loggingDebug) {
               log.debug("loadPlayerObject instanceOid " + instanceOid + " END return true");
            }

            return true;
         }
      }
   }

   protected boolean processLoginHelper(ClientConnection con, Player player) {
      OID playerOid = player.getOid();
      ObjectInfo objInfo = WorldManagerClient.getObjectInfo(playerOid);
      if (objInfo == null) {
         Log.error("processLogin: Could not get player ObjectInfo oid=" + playerOid);
         return false;
      } else {
         if (Log.loggingDebug) {
            log.debug("processLoginHelper objInfo " + objInfo.instanceOid);
         }

         if (World.FollowsTerrainOverride != null) {
            Log.debug("using follows terrain override");
            objInfo.followsTerrain = World.FollowsTerrainOverride;
         }

         if (Log.loggingDebug) {
            Log.debug("processLogin: got object info: " + objInfo);
         }

         player.setName(objInfo.name);
         InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(objInfo.instanceOid, -262145);
         if (Log.loggingDebug) {
            log.debug("InstanceInfo " + instanceInfo + " " + instanceInfo.playerOid + " " + instanceInfo.templateID + " " + instanceInfo.groupOid + " " + instanceInfo.guildId);
         }

         if (instanceInfo == null) {
            Log.error("processLogin: unknown instanceOid=" + objInfo.instanceOid);
            return false;
         } else {
            if (Log.loggingDebug) {
               Log.debug("processLogin: sending template (scene) name: " + instanceInfo.templateName);
            }

            Event worldFileEvent = new WorldFileEvent(instanceInfo.templateName);
            con.send(worldFileEvent.toBytes());
            player.sceneLoading(true);
            Log.debug("INFO: process login helper");
            con.send(objInfo.toBuffer(playerOid));
            DisplayContext dc = WorldManagerClient.getDisplayContext(playerOid);
            ModelInfoEvent modelInfoEvent = new ModelInfoEvent(playerOid);
            modelInfoEvent.setDisplayContext(dc);
            if (Log.loggingDebug) {
               Log.debug("processLogin: got dc: " + dc);
            }

            con.send(modelInfoEvent.toBytes());
            Map<String, DisplayContext> childMap = dc.getChildDCMap();
            if (childMap != null && !childMap.isEmpty()) {
               Iterator var10 = childMap.keySet().iterator();

               while(var10.hasNext()) {
                  String slot = (String)var10.next();
                  DisplayContext attachDC = (DisplayContext)childMap.get(slot);
                  if (attachDC == null) {
                     throw new AORuntimeException("attach DC is null for obj: " + playerOid);
                  }

                  OID attacheeOID = attachDC.getObjRef();
                  if (attacheeOID == null) {
                     throw new AORuntimeException("attachee oid is null for obj: " + playerOid);
                  }

                  if (Log.loggingDebug) {
                     Log.debug("processLogin: sending attach message to " + playerOid + " attaching to obj " + playerOid + ", object being attached=" + attacheeOID + " to slot " + slot + ", attachmentDC=" + attachDC);
                  }

                  AttachEvent event = new AttachEvent(playerOid, attacheeOID, slot, attachDC);
                  con.send(event.toBytes());
               }

               Log.debug("processLogin: done with processing attachments");
            }

            if (this.perceptionFilter.addTarget(playerOid)) {
               FilterUpdate filterUpdate = new FilterUpdate(1);
               filterUpdate.addFieldValue(1, playerOid);
               Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
               this.responderFilter.addTarget(playerOid);
               this.responderFilter2.addTarget(playerOid);
               Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
               Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
            }

            LoginMessage loginMessage = new LoginMessage(playerOid, objInfo.name);
            loginMessage.setInstanceOid(objInfo.instanceOid);
            loginMessage.setProxy(this.getName());
            atavism.server.plugins.ProxyPlugin.AsyncRPCCallback asyncRPCCallback = new atavism.server.plugins.ProxyPlugin.AsyncRPCCallback(player, "processLogin: got LoginMessage response");
            int expectedResponses = Engine.getAgent().sendBroadcastRPC(loginMessage, asyncRPCCallback);
            asyncRPCCallback.waitForResponses(expectedResponses);
            WorldManagerClient.updateObject(playerOid, playerOid);
            TargetedExtensionMessage spawnBegin = new TargetedExtensionMessage(playerOid, playerOid);
            spawnBegin.setExtensionType("ao.SCENE_BEGIN");
            spawnBegin.setProperty("action", "login");
            spawnBegin.setProperty("name", instanceInfo.name);
            spawnBegin.setProperty("templateName", instanceInfo.templateName);
            TargetedExtensionMessage spawnEnd = new TargetedExtensionMessage(playerOid, playerOid);
            spawnEnd.setExtensionType("ao.SCENE_END");
            spawnEnd.setProperty("action", "login");
            spawnEnd.setProperty("name", instanceInfo.name);
            spawnEnd.setProperty("templateName", instanceInfo.templateName);
            Integer perceptionCount = WorldManagerClient.spawn(playerOid, spawnBegin, spawnEnd);
            if (perceptionCount < 0) {
               Log.error("processLogin: spawn failed error=" + perceptionCount + " playerOid=" + playerOid);
               return perceptionCount == -2 ? false : false;
            } else {
               if (perceptionCount == 0 && player.supportsLoadingState()) {
                  player.setLoadingState(1);
                  con.send((new LoadingStateEvent(false)).toBytes());
               }

               if (Log.loggingDebug) {
                  Log.debug("processLogin: During login, perceptionCount is " + perceptionCount);
                  Log.debug("processLogin: spawned player, master playerOid=" + playerOid);
               }

               if (Log.loggingDebug) {
                  Log.debug("processLogin: sending over instance information for player " + playerOid + ", instance=" + instanceInfo.name + ", instanceOid=" + instanceInfo.oid);
               }

               this.updateInstancePerception(player.getOid(), (OID)null, instanceInfo.oid, instanceInfo.name);
               return true;
            }
         }
      }
   }

   public ProxyLoginCallback getProxyLoginCallback() {
      return this.proxyLoginCallback;
   }

   public void setProxyLoginCallback(ProxyLoginCallback callback) {
      this.proxyLoginCallback = callback;
   }

   private boolean instanceEntryAllowed(OID playerOid, OID instanceOid, Point location) {
      return instanceOid == null ? false : this.instanceEntryCallback.instanceEntryAllowed(playerOid, instanceOid, location);
   }

   public InstanceEntryCallback getInstanceEntryCallback() {
      return this.instanceEntryCallback;
   }

   public void setInstanceEntryCallback(InstanceEntryCallback callback) {
      this.instanceEntryCallback = callback;
   }

   public void processRequestQuestInfo(ClientConnection con, RequestQuestInfo event) {
      OID npcOid = event.getQuestNpcOid();
      Player player = this.verifyPlayer("processRequestQuestInfo", event, con);
      if (Log.loggingDebug) {
         Log.debug("processRequestQuestInfo: player=" + player + ", npc=" + npcOid);
      }

      QuestClient.requestQuestInfo(npcOid, player.getOid());
   }

   public void processQuestResponse(ClientConnection con, QuestResponse event) {
      Player player = this.verifyPlayer("processQuestResponse", event, con);
      boolean acceptStatus = event.getResponse();
      OID npcOid = event.getQuestNpcOid();
      OID questOid = event.getQuestId();
      if (Log.loggingDebug) {
         Log.debug("processQuestResponse: player=" + player + ", npcOid=" + npcOid + ", acceptStatus=" + acceptStatus);
      }

      QuestResponseMessage msg = new QuestResponseMessage(npcOid, player.getOid(), questOid, acceptStatus);
      Engine.getAgent().sendBroadcast(msg);
   }

   public void processReqConcludeQuest(ClientConnection con, ConcludeQuest event) {
      Player player = this.verifyPlayer("processReqConcludeQuest", event, con);
      OID mobOid = event.getQuestNpcOid();
      if (Log.loggingDebug) {
         Log.debug("processReqConclude: player=" + player + ", mobOid=" + mobOid);
      }

      QuestClient.requestConclude(mobOid, player.getOid());
   }

   public void connectionReset(ClientConnection con) {
      Player player = (Player)con.getAssociation();
      if (player == null) {
         Log.info("ProxyPlugin: DISCONNECT remote=" + con);
      } else {
         if (Log.loggingInfo) {
            Log.info("ProxyPlugin: DISCONNECT remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName() + " player=" + player);
            Log.info("ProxyPlugin: DISCONNECT remote=" + con + " player=" + player);
         }

         this.playerManager.logout(player);
         atavism.server.plugins.ProxyPlugin.ConnectionResetMessage message = new atavism.server.plugins.ProxyPlugin.ConnectionResetMessage(this, con, player);
         message.setEnqueueTime();
         this.messageQQ.insert(player, message);
      }
   }

   protected void processConnectionResetInternal(atavism.server.plugins.ProxyPlugin.ConnectionResetMessage message) {
      long startTime = System.currentTimeMillis();
      ClientConnection con = message.getConnection();
      Player player = message.getPlayer();
      OID playerOid = player.getOid();
      if (Log.loggingInfo) {
         Log.info("ProxyPlugin: LOGOUT_BEGIN remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName());
      }

      if (player.getStatus() != 3) {
         log.error("processConnectionReset: player status is " + Player.statusToString(player.getStatus()) + " should be " + Player.statusToString(3));
         player.setStatus(3);
      }

      try {
         try {
            if (!WorldManagerClient.despawn(playerOid)) {
               log.warn("processConnectionReset: despawn player failed for " + playerOid);
            }
         } catch (Exception var13) {
            log.warn("processConnectionReset: despawn player failed for " + playerOid + " " + var13);
         }

         if (Log.loggingDebug) {
            Log.debug("processConnectionResetInternal Removing perceptionFilter for palyer: " + playerOid);
         }

         if (this.perceptionFilter.removeTarget(playerOid)) {
            FilterUpdate filterUpdate = new FilterUpdate(1);
            filterUpdate.removeFieldValue(1, playerOid);
            if (Log.loggingDebug) {
               Log.debug("processConnectionResetInternal Removing perceptionFilter applyFilterUpdate for palyer: " + playerOid);
            }

            Engine.getAgent().applyFilterUpdate(this.perceptionSubId, filterUpdate);
            if (Log.loggingDebug) {
               Log.debug("processConnectionResetInternal Removing responderFilter for palyer: " + playerOid);
            }

            this.responderFilter.removeTarget(playerOid);
            this.responderFilter2.removeTarget(playerOid);
            if (Log.loggingDebug) {
               Log.debug("processConnectionResetInternal Removing perceptionFilter applyFilterUpdate for palyer: " + playerOid);
            }

            Engine.getAgent().applyFilterUpdate(this.responderSubId, filterUpdate);
            Engine.getAgent().applyFilterUpdate(this.responderSubId2, filterUpdate);
         }

         LogoutMessage logoutMessage = new LogoutMessage(playerOid, player.getName());
         if (Log.loggingDebug) {
            Log.debug("processConnectionResetInternal: Send LogoutMessage for player: " + playerOid + "  and wait for response");
         }

         atavism.server.plugins.ProxyPlugin.AsyncRPCCallback asyncRPCCallback = new atavism.server.plugins.ProxyPlugin.AsyncRPCCallback(player, "processLogout: got LogoutMessage response");
         int expectedResponses = Engine.getAgent().sendBroadcastRPC(logoutMessage, asyncRPCCallback);
         if (Log.loggingDebug) {
            Log.debug("processConnectionResetInternal: Send LogoutMessage for player: " + playerOid + "  and wait for response expectedResponses=" + expectedResponses);
         }

         asyncRPCCallback.waitForResponses(expectedResponses);
         OID accountID = this.aDB.getAccountForCharacter(playerOid);
         if (Log.loggingDebug) {
            Log.debug("Removing connection from client connection map for account: " + accountID);
         }

         if (this.clientConnections.containsKey(accountID) && ((ClientConnection)this.clientConnections.get(accountID)).isOpen()) {
            Prometheus.registry().counter("rdp_connection_closed", new String[]{"reason", "internal_reset"}).increment();
            ((ClientConnection)this.clientConnections.get(accountID)).close();
         }

         this.clientConnections.remove(accountID);
         if (!ObjectManagerClient.unloadObject(playerOid)) {
            log.warn("processConnectionReset: unloadObject failed oid=" + playerOid);
         }
      } catch (NoRecipientsException var14) {
         log.exception("ProxyPlugin.processConnectionResetInternal(): NoRecipientsException ", var14);
      } catch (RPCTimeoutException var15) {
         log.exception("ProxyPlugin.processConnectionResetInternal(): RPCTimeoutException ", var15);
      } catch (Exception var16) {
         log.exception("ProxyPlugin.processConnectionResetInternal(): Exception ", var16);
      }

      this.messageQQ.removeKey(player);
      this.eventQQ.removeKey(player);
      con.closeAggregator();
      this.playerManager.removeStaticPerception(player, playerOid);
      this.playerManager.removePlayer(playerOid);
      if (Log.loggingInfo) {
         Log.info("ProxyPlugin: LOGOUT_END remote=" + con + " playerOid=" + player.getOid() + " name=" + player.getName() + " in-queue=" + (startTime - message.getEnqueueTime()) + " processing=" + (System.currentTimeMillis() - startTime) + " nPlayers=" + this.playerManager.getPlayerCount());
      }

      synchronized(player) {
         player.clearConnection();
         player.notifyAll();
      }
   }

   protected void processPlayerHa(ClientConnection con, PlayerHaEvent event) {
      if (Log.loggingDebug) {
         Log.debug("processPlayerHa: got dir loc orient event: " + event);
      }

      Player player = this.verifyPlayer("processPlayerHa", event, con);
      long stime = System.currentTimeMillis();
      long ctime = event.getTime();
      long lctime = 0L;
      long lstime = 0L;

      try {
         lctime = (Long)this.playerLastClientTime.get(player.getOid());
      } catch (Exception var20) {
      }

      try {
         lstime = (Long)this.playerLastServerTime.get(player.getOid());
      } catch (Exception var19) {
      }

      this.playerLastClientTime.put(player.getOid(), event.getTime());
      this.playerLastServerTime.put(player.getOid(), stime);
      if (lctime > 0L && lstime > 0L && stime - lstime < (long)SpeedhackMinDiff) {
         log.error("SPEEDHACK detected plyOid=" + player.getOid() + " Ct=" + ctime + " LCT=" + lctime + " ST=" + stime + " LST=" + lstime + " dst=" + (stime - lstime) + " dct=" + (ctime - lctime));
         long count = 0L;

         try {
            count = (Long)this.playerSpeedHackCount.get(player.getOid());
         } catch (Exception var18) {
         }

         ++count;
         this.playerSpeedHackCount.put(player.getOid(), count);
         long fdtime = 0L;

         try {
            fdtime = (Long)this.playerFirstSpeedHackTime.get(player.getOid());
         } catch (Exception var17) {
         }

         if (fdtime == 0L) {
            fdtime = stime;
            this.playerFirstSpeedHackTime.put(player.getOid(), stime);
         }

         if (SpeedhackChatMsg.length() > 1) {
            TargetedComMessage comMsg = new TargetedComMessage();
            comMsg.setString(SpeedhackChatMsg);
            comMsg.setChannel(0);
            comMsg.setChatterName("Admin");
            comMsg.setTarget(player.getOid());
            Engine.getAgent().sendBroadcast(comMsg);
         }

         HashMap<String, Serializable> logData = new HashMap();
         logData.put("serverDeltaTime", stime - lstime);
         logData.put("clientDeltaTime", ctime - lctime);
         logData.put("firstDetection", fdtime);
         logData.put("count", count);
         DataLoggerClient.logData("SPEEDHACK", player.getOid(), (OID)null, (OID)null, logData);
         if (count > (long)SpeedhackCountToDisconect) {
            Prometheus.registry().counter("rdp_connection_closed", new String[]{"reason", "speed_hack"}).increment();
            con.close();
            this.playerLastClientTime.remove(player.getOid());
            this.playerLastServerTime.remove(player.getOid());
            this.playerFirstSpeedHackTime.remove(player.getOid());
            this.playerSpeedHackCount.remove(player.getOid());
         }
      }

   }

   protected void processDirLocOrient(ClientConnection con, DirLocOrientEvent event) {
      if (Log.loggingDebug) {
         Log.debug("processDirLocOrient: got dir loc orient event: " + event);
      }

      Player player = this.verifyPlayer("processDirLoc", event, con);
      BasicWorldNode wnode = new BasicWorldNode();
      wnode.setDir(event.getDir());
      wnode.setLoc(event.getLoc());
      wnode.setOrientation(event.getQuaternion());
      wnode.time = event.getTime();
      wnode.mid = event.getId();
      wnode.cid = event.getUId();
      WorldManagerClient.updateWorldNode(player.getOid(), wnode);
   }

   protected void processCom(ClientConnection con, ComEvent event) {
      Player player = this.verifyPlayer("processCom", event, con);
      if (Log.loggingInfo) {
         Log.info("ProxyPlugin: CHAT_SENT player=" + player + " channel=" + event.getChannelId() + " msg=[" + event.getMessage() + "]");
      }

      log.debug("processCom: CHAT_SENT");
      if (!this.aDB.isOnBlackList(player.getOid(), event.getObjectOid())) {
         this.incrementChatCount();
         ChatClient.sendChatMsg(player.getOid(), player.getName(), event.getChannelId(), event.getMessage());
      }
   }

   protected void processCommand(ClientConnection con, CommandEvent event) {
      Player player = this.verifyPlayer("processCommand", event, con);
      String cmd = event.getCommand().split(" ")[0];
      if (Log.loggingDebug) {
         log.debug("processCommand: cmd=" + cmd + ", fullCmd=" + event.getCommand());
      }

      this.commandMapLock.lock();

      atavism.server.plugins.ProxyPlugin.RegisteredCommand command;
      try {
         command = (atavism.server.plugins.ProxyPlugin.RegisteredCommand)this.commandMap.get(cmd);
      } finally {
         this.commandMapLock.unlock();
      }

      if (command == null) {
         Log.warn("processCommand: no parser for command: " + event.getCommand());
         command = (atavism.server.plugins.ProxyPlugin.RegisteredCommand)this.commandMap.get("/unknowncmd");
         if (command != null) {
            Engine.setCurrentPlugin(this);
            command.parser.parse(event);
            Engine.setCurrentPlugin((EnginePlugin)null);
         }

      } else {
         Engine.setCurrentPlugin(this);
         if (command.access.allowed(event, this)) {
            command.parser.parse(event);
         } else {
            Log.warn("Player " + player + " not allowed to run command '" + event.getCommand() + "'");
         }

         Engine.setCurrentPlugin((EnginePlugin)null);
      }
   }

   protected void processAutoAttack(ClientConnection con, AutoAttackEvent event) {
      CombatClient.autoAttack(event.getAttackerOid(), event.getTargetOid(), event.getAttackStatus());
   }

   protected void processActivateItem(ClientConnection con, ActivateItemEvent event) {
      InventoryClient.activateObject(event.getItemOid(), event.getObjectOid(), event.getTargetOid());
   }

   protected void processAbilityStatusEvent(ClientConnection con, AbilityStatusEvent event) {
      Player player = (Player)con.getAssociation();
      AbilityStatusMessage msg = new AbilityStatusMessage(CombatClient.MSG_TYPE_ABILITY_STATUS, player.getOid(), event.getPropertyMap());
      Engine.getAgent().sendBroadcast(msg);
   }

   protected void processLogout(ClientConnection con, LogoutEvent event) {
   }

   protected void processSceneLoaded(ClientConnection con, SceneLoadedEvent event) {
      Player player = (Player)con.getAssociation();
      player.sceneLoading(false);
      if (Log.loggingDebug) {
         Log.debug("SCENE: sceneLoading set to false for player: " + player.getOid());
      }

   }

   protected void processExtensionMessageEvent(ClientConnection con, ExtensionMessageEvent event) {
      String key = (String)event.getPropertyMap().get("ext_msg_subtype");
      OID target = event.getTargetOid();
      Player player = (Player)con.getAssociation();
      if (Log.loggingDebug) {
         Log.debug("processExtensionMessageEvent: " + player + " subType=" + key + " target=" + target);
      }

      List<ProxyExtensionHook> proxyHookList = (List)this.extensionHooks.get(key);
      if (proxyHookList == null) {
         if (target != null) {
            TargetedExtensionMessage msg = new TargetedExtensionMessage(WorldManagerClient.MSG_TYPE_EXTENSION, target, player.getOid(), event.getClientTargeted(), event.getPropertyMap());
            if (event.getClientTargeted()) {
               msg.setMsgType(WorldManagerClient.MSG_TYPE_P2P_EXTENSION);
               if (this.allowClientToClientMessage(player, target, msg)) {
                  Engine.getAgent().sendBroadcast(msg);
               }
            } else {
               MessageType msgType = this.getExtensionMessageType(key);
               if (msgType == null) {
                  Log.error("processExtensionMessageEvent: key '" + key + "' has no corresponding MessageType");
                  return;
               }

               msg.setMsgType(msgType);
               Engine.getAgent().sendBroadcast(msg);
            }
         } else {
            MessageType msgType = this.getExtensionMessageType(key);
            if (msgType == null) {
               Log.error("processExtensionMessageEvent: key '" + key + "' has no corresponding MessageType");
               return;
            }

            ExtensionMessage msg = new ExtensionMessage(msgType, player.getOid(), event.getPropertyMap());
            Engine.getAgent().sendBroadcast(msg);
         }

      } else {
         Iterator var7 = proxyHookList.iterator();

         while(var7.hasNext()) {
            ProxyExtensionHook hook = (ProxyExtensionHook)var7.next();
            hook.processExtensionEvent(event, player, this);
         }

      }
   }

   public void registerExtensionSubtype(String subtype, MessageType type) {
      this.extensionMessageRegistry.put(subtype, type);
   }

   public MessageType unregisterExtensionSubtype(String subtype) {
      return (MessageType)this.extensionMessageRegistry.remove(subtype);
   }

   public MessageType getExtensionMessageType(String subtype) {
      return (MessageType)this.extensionMessageRegistry.get(subtype);
   }

   public boolean allowClientToClientMessage(Player sender, OID targetOid, TargetedExtensionMessage message) {
      return this.defaultAllowClientToClientMessage;
   }

   protected boolean specialCaseNewProcessing(ObjectNote objectNote, Player player) {
      long start = System.currentTimeMillis();
      ClientConnection con = player.getConnection();
      OID objOid = objectNote.getSubject();
      ObjectType objType = objectNote.getObjectType();
      if (objType == ObjectTypes.light) {
         Log.debug("specialCaseNewProcessing: got a light object");
         LightData lightData = (LightData)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, Light.LightDataPropertyKey);
         if (Log.loggingDebug) {
            Log.debug("specialCaseNewProcessing: light data=" + lightData);
         }

         NewLightEvent lightEvent = new NewLightEvent(player.getOid(), objOid, lightData);
         con.send(lightEvent.toBytes());
         return true;
      } else if (objType.equals(WorldManagerClient.TEMPL_OBJECT_TYPE_TERRAIN_DECAL)) {
         Log.debug("specialCaseNewProcessing: got a terrain decal object");
         TerrainDecalData decalData = (TerrainDecalData)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, WorldManagerClient.TEMPL_TERRAIN_DECAL_DATA);
         if (Log.loggingDebug) {
            Log.debug("specialCaseNewProcessing: terrain decal data=" + decalData);
         }

         NewTerrainDecalEvent decalEvent = new NewTerrainDecalEvent(objOid, decalData);
         con.send(decalEvent.toBytes());
         return true;
      } else if (objType.equals(WorldManagerClient.TEMPL_OBJECT_TYPE_POINT_SOUND)) {
         Log.debug("specialCaseNewProcessing: got a point sound object");
         List<SoundData> soundData = (List)EnginePlugin.getObjectProperty(objOid, Namespace.WORLD_MANAGER, WorldManagerClient.TEMPL_SOUND_DATA_LIST);
         if (Log.loggingDebug) {
            Log.debug("specialCaseNewProcessing: sound data=" + soundData);
         }

         SoundMessage soundMsg = new SoundMessage(objOid);
         soundMsg.setSoundData(soundData);
         con.send(soundMsg.toBuffer());
         return true;
      } else {
         PerceptionInfo perceptionInfo = (PerceptionInfo)objectNote.getObjectInfo();
         if (perceptionInfo.objectInfo == null) {
            return true;
         } else {
            MobPathMessage pathMsg = (MobPathMessage)perceptionInfo.objectInfo.getProperty(WorldManagerClient.MOB_PATH_PROPERTY);
            if (Log.loggingDebug) {
               Log.debug("INFO: MobPathMessage special case with player/npc: " + perceptionInfo.objectInfo.name);
            }

            con.send(perceptionInfo.objectInfo.toBuffer(player.getOid()));
            if (Log.loggingDebug) {
               Log.debug("INFO: specialCaseNewProcessing " + perceptionInfo.displayContext);
            }

            if (perceptionInfo.displayContext != null) {
               ModelInfoEvent modelInfoEvent = new ModelInfoEvent(objOid);
               modelInfoEvent.setDisplayContext(perceptionInfo.displayContext);
               con.send(modelInfoEvent.toBytes());
            } else if (Log.loggingDebug) {
               Log.debug("No display context for " + objOid + " " + perceptionInfo.objectInfo);
            }

            if (pathMsg != null) {
               if (pathMsg.pathExpired()) {
                  if (Log.loggingDebug) {
                     Log.debug("specialCaseNewProcessing: for mob " + objOid + ", last mob path expired " + pathMsg.toString());
                  }
               } else {
                  if (Log.loggingDebug) {
                     Log.debug("specialCaseNewProcessing: for mob " + objOid + ", sending last mob path " + pathMsg.toString());
                  }

                  AOByteBuffer pathBuf = pathMsg.toBuffer();
                  con.send(pathBuf);
               }
            }

            Map<String, DisplayContext> childMap = null;
            if (perceptionInfo.displayContext != null) {
               childMap = perceptionInfo.displayContext.getChildDCMap();
            }

            if (childMap != null && !childMap.isEmpty()) {
               Iterator var11 = childMap.keySet().iterator();

               while(var11.hasNext()) {
                  String slot = (String)var11.next();
                  DisplayContext attachDC = (DisplayContext)childMap.get(slot);
                  if (attachDC == null) {
                     throw new AORuntimeException("attach DC is null for obj: " + objOid);
                  }

                  OID attacheeOID = attachDC.getObjRef();
                  if (attacheeOID == null) {
                     throw new AORuntimeException("attachee oid is null for obj: " + objOid);
                  }

                  if (Log.loggingDebug) {
                     Log.debug("specialCaseNewProcessing: sending attach message to " + player.getOid() + " attaching to obj " + objOid + ", object being attached=" + attacheeOID + " to slot " + slot + ", attachmentDC=" + attachDC);
                  }

                  AttachEvent event = new AttachEvent(objOid, attacheeOID, slot, attachDC);
                  con.send(event.toBytes());
               }

               if (Log.loggingDebug) {
                  Log.debug("specialCaseNewProcessing: done with processing attachments");
               }
            }

            long finish = System.currentTimeMillis();
            if (Log.loggingDebug) {
               Log.debug("specialCaseNewProcessing: finished.\tplayerOid=" + player.getOid() + ", oid=" + objOid + " in " + (finish - start) + " ms");
            }

            return false;
         }
      }
   }

   protected boolean specialCaseFreeProcessing(ObjectNote objectNote, Player player) {
      if (player.getOid().equals(objectNote.getSubject())) {
         Log.debug("ignoring free object message to self");
         return true;
      } else {
         ClientConnection con = player.getConnection();
         if (!con.isOpen()) {
            con = null;
         }

         OID objOid = objectNote.getSubject();
         if (objectNote.getObjectType() == ObjectTypes.road) {
            if (Log.loggingDebug) {
               Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", roadSegmentOid=" + objOid);
            }

            this.handleFreeRoad(con, objOid);
            return true;
         } else if (objectNote.getObjectType().equals(WorldManagerClient.TEMPL_OBJECT_TYPE_TERRAIN_DECAL)) {
            if (Log.loggingDebug) {
               Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", decalOid=" + objOid);
            }

            FreeTerrainDecalEvent decalEvent = new FreeTerrainDecalEvent(objOid);
            if (con != null) {
               con.send(decalEvent.toBytes());
            }

            return true;
         } else {
            if (Log.loggingDebug) {
               Log.debug("specialCaseFreeProcessing: playerOid=" + player.getOid() + ", objOid=" + objOid);
            }

            NotifyFreeObjectEvent freeEvent = new NotifyFreeObjectEvent(player.getOid(), objOid);
            if (con != null) {
               con.send(freeEvent.toBytes());
            }

            return false;
         }
      }
   }

   protected void handleFreeRoad(ClientConnection con, OID objOid) {
      FreeRoadMessage freeRoadMsg = new FreeRoadMessage(objOid);
      AOByteBuffer buf = freeRoadMsg.toBuffer();
      if (con != null) {
         con.send(buf);
      }

   }

   public static void addStaticPerception(OID playerOid, OID oid) {
      addStaticPerception(playerOid, oid, (String)null, (ObjectType)null, false);
   }

   public static void addStaticPerception(OID oid, OID oid2, String name, ObjectType type) {
      addStaticPerception(oid, oid2, name, type, true);
   }

   private static void addStaticPerception(OID playerOid, OID oid, String name, ObjectType type, boolean hasObjectInfo) {
      atavism.server.plugins.ProxyPlugin.AddStaticPerceptionMessage message = new atavism.server.plugins.ProxyPlugin.AddStaticPerceptionMessage(MSG_TYPE_ADD_STATIC_PERCEPTION);
      message.setTarget(playerOid);
      message.setSubject(oid);
      message.setName(name);
      message.setType(type);
      message.setHasObjectInfo(hasObjectInfo);
      Engine.getAgent().sendBroadcast(message);
   }

   public static void removeStaticPerception(OID playerOid, OID oid) {
      TargetMessage message = new TargetMessage(MSG_TYPE_REMOVE_STATIC_PERCEPTION);
      message.setTarget(playerOid);
      message.setSubject(oid);
      Engine.getAgent().sendBroadcast(message);
   }

   protected void processPlayerIgnoreList(Player player) {
      if (player.getStatus() == 3) {
         Log.error("ProxyPlugin.processPlayerIgnoreList: Aborting... player.getStatus() is STATUS_LOGOUT");
      } else {
         this.sendPlayerIgnoreList(player);
      }
   }

   protected void sendPlayerIgnoreList(Player player) {
      String missing = " Missing ";
   }

   public void updateIgnoredOids(Player player, List<OID> nowIgnored, List<OID> noLongerIgnored) {
   }

   public List<Object> matchingPlayers(Player player, String playerName, Boolean exactMatch) {
      boolean match = exactMatch == null ? true : exactMatch;
      List<Object> matchLists = Engine.getDatabase().getOidsAndNamesMatchingName(playerName, match);
      List<OID> oids = (List)matchLists.get(0);
      List<String> names = (List)matchLists.get(1);
      if (Log.loggingDebug) {
         log.debug("ProxyPlugin.matchingPlayers: For player " + player.getOid() + ", found " + (oids == null ? 0 : oids.size()) + " players: " + Database.makeOidCollectionString(oids) + " " + (match ? "exactly matching" : "starting with") + " name '" + playerName + "':" + Database.makeNameCollectionString(names));
      }

      return matchLists;
   }

   public boolean isOnBlockList2(OID playerOid, OID targetOid) {
      if (Log.loggingDebug) {
         log.debug("IsOnBlockList: SocialPlugin  started for: " + playerOid);
      }

      boolean isOnBlockList = this.aDB.isOnBlackList(playerOid, targetOid);
      String targetName;
      if (isOnBlockList) {
         targetName = WorldManagerClient.getObjectInfo(targetOid).name;
         EventMessageHelper.SendErrorEvent(playerOid, "ErrorPlayerOnBlockList", 0, targetName);
      } else {
         isOnBlockList = this.aDB.isOnBlackList(targetOid, playerOid);
         if (isOnBlockList) {
            targetName = WorldManagerClient.getObjectInfo(targetOid).name;
            EventMessageHelper.SendErrorEvent(playerOid, "ErrorPlayerYourOnBlockList", 0, targetName);
         }
      }

      if (Log.loggingDebug) {
         log.debug("IsOnBlockList: SocialPlugin  finished for: " + playerOid);
      }

      return isOnBlockList;
   }

   private boolean isPlayerConnectionValid(Player player) {
      ClientConnection con = player.getConnection();
      return con != null && con.isOpen();
   }

   public static OID handleFullInstance(int instanceTemplateID, InstanceInfo instanceInfo) {
      if (Log.loggingDebug) {
         Log.debug("POP: instance full with template: " + instanceTemplateID);
      }

      int instanceNum = 1;
      String instanceName = "";
      InstanceTemplate island = InstanceClient.getInstanceTemplate(instanceTemplateID);

      OID instanceOid;
      while(true) {
         instanceName = island.getName() + "_" + instanceNum;
         instanceOid = InstanceClient.getInstanceOid(instanceName);
         if (instanceOid != null) {
            instanceInfo = InstanceClient.getInstanceInfo(instanceOid, -262145);
            if (instanceInfo.populationLimit < 1 || instanceInfo.playerPopulation < instanceInfo.populationLimit) {
               break;
            }
         } else {
            Template overrideTemplate = new Template();
            overrideTemplate.put(Namespace.INSTANCE, "name", instanceName);
            overrideTemplate.setName(instanceName);
            instanceOid = InstanceClient.createInstance(instanceTemplateID, overrideTemplate);
            if (instanceOid != null) {
               break;
            }
         }

         ++instanceNum;
      }

      return instanceOid;
   }

   private void updateInstancePerception(OID playerOid, OID prevInstanceOid, OID destInstanceOid, String destInstanceName) {
      if (prevInstanceOid != null) {
         removeStaticPerception(playerOid, prevInstanceOid);
      }

      addStaticPerception(playerOid, destInstanceOid, destInstanceName, ObjectTypes.instance);
   }

   protected void pushInstanceRestorePoint(Player player, BasicWorldNode loc) {
      OID playerOid = player.getOid();
      if (Log.loggingDebug) {
         log.debug("pushInstanceRestorePoint " + playerOid);
      }

      InstanceRestorePoint restorePoint = new InstanceRestorePoint();
      restorePoint.setInstanceOid(loc.getInstanceOid());
      restorePoint.setLoc(loc.getLoc());
      restorePoint.setOrientation(loc.getOrientation());
      InstanceInfo instanceInfo = InstanceClient.getInstanceInfo(loc.getInstanceOid(), 8);
      restorePoint.setInstanceID(instanceInfo.templateID);
      LinkedList<Object> restoreStack = (LinkedList)EnginePlugin.getObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack");
      if (restoreStack == null) {
         restoreStack = new LinkedList();
      }

      restoreStack.add(restorePoint);
      EnginePlugin.setObjectProperty(playerOid, Namespace.OBJECT_MANAGER, "instanceStack", restoreStack);
   }

   protected void sendOceanData(OceanData oceanData, Player player) {
      TargetedExtensionMessage oceanMsg = new ClientParameterMessage(player.getOid());
      oceanMsg.setProperty("Ocean.DisplayOcean", oceanData.displayOcean.toString());
      if (oceanData.useParams != null) {
         oceanMsg.setProperty("Ocean.UseParams", oceanData.useParams.toString());
      }

      if (oceanData.waveHeight != null) {
         oceanMsg.setProperty("Ocean.WaveHeight", oceanData.waveHeight.toString());
      }

      if (oceanData.seaLevel != null) {
         oceanMsg.setProperty("Ocean.SeaLevel", oceanData.seaLevel.toString());
      }

      if (oceanData.bumpScale != null) {
         oceanMsg.setProperty("Ocean.BumpScale", oceanData.bumpScale.toString());
      }

      if (oceanData.bumpSpeedX != null) {
         oceanMsg.setProperty("Ocean.BumpSpeedX", oceanData.bumpSpeedX.toString());
      }

      if (oceanData.bumpSpeedZ != null) {
         oceanMsg.setProperty("Ocean.BumpSpeedZ", oceanData.bumpSpeedZ.toString());
      }

      if (oceanData.textureScaleX != null) {
         oceanMsg.setProperty("Ocean.TextureScaleX", oceanData.textureScaleX.toString());
      }

      if (oceanData.textureScaleZ != null) {
         oceanMsg.setProperty("Ocean.TextureScaleZ", oceanData.textureScaleZ.toString());
      }

      if (oceanData.deepColor != null) {
         oceanMsg.setProperty("Ocean.DeepColor", oceanData.deepColor.toString());
      }

      if (oceanData.shallowColor != null) {
         oceanMsg.setProperty("Ocean.ShallowColor", oceanData.shallowColor.toString());
      }

      player.getConnection().send(oceanMsg.toBuffer(player.getVersion()));
   }

   protected Player verifyPlayer(String context, Event event, ClientConnection con) {
      Player player = (Player)con.getAssociation();
      if (!player.getOid().equals(event.getObjectOid())) {
         throw new AORuntimeException(context + ": con doesn't match player " + player + " against eventOid " + event.getObjectOid());
      } else {
         return player;
      }
   }

   public void incrementChatCount() {
      ++this.chatSentCount;
   }

   public void incrementPrivateChatCount() {
      ++this.privateChatSentCount;
   }

   public void addAdmin(OID oid) {
      if (Log.loggingDebug) {
         log.debug("ProxyPlugin.addAdmin: adding oid " + oid);
      }

      this.lock.lock();

      try {
         this.adminSet.add(oid);
      } finally {
         this.lock.unlock();
      }

   }

   public Set<OID> getAdmins() {
      this.lock.lock();

      HashSet var1;
      try {
         var1 = new HashSet(this.adminSet);
      } finally {
         this.lock.unlock();
      }

      return var1;
   }

   public boolean isAdmin(OID playerOid) {
      this.lock.lock();

      boolean var2;
      try {
         if (playerOid != null) {
            AccountDatabase aDB = new AccountDatabase(false);
            int status = aDB.getCharacterAccountStatus(playerOid);
            boolean var4 = status == 5;
            return var4;
         }

         var2 = false;
      } finally {
         this.lock.unlock();
      }

      return var2;
   }

   public int GetConnectionLimit() {
      return this.connectionLimit;
   }

   protected Object createMBeanInstance() {
      return new atavism.server.plugins.ProxyPlugin.ProxyJMX(this);
   }

   private String getTemp() {
      return "47bedc488b0106b2219dd2e2ff5524fd";
   }

   // $FF: synthetic method
   static SquareQueue access$200(ProxyPlugin x0) {
      return x0.eventQQ;
   }

   // $FF: synthetic method
   static String access$300(ProxyPlugin x0) {
      return x0.getTemp();
   }

   // $FF: synthetic method
   static int access$402(ProxyPlugin x0, int x1) {
      return x0.connectionLimit = x1;
   }

   // $FF: synthetic method
   static int access$400(ProxyPlugin x0) {
      return x0.connectionLimit;
   }

   // $FF: synthetic method
   static ObjectLockManager access$1100(ProxyPlugin x0) {
      return x0.getObjectLockManager();
   }

   // $FF: synthetic method
   static int access$1200(ProxyPlugin x0) {
      return x0.instanceEntryCount;
   }

   // $FF: synthetic method
   static int access$1300(ProxyPlugin x0) {
      return x0.chatSentCount;
   }

   // $FF: synthetic method
   static int access$1400(ProxyPlugin x0) {
      return x0.privateChatSentCount;
   }

   // $FF: synthetic method
   static ExecutorService access$1500(ProxyPlugin x0) {
      return x0.logoutExecutor;
   }

   // $FF: synthetic method
   static boolean access$1600(ProxyPlugin x0, Player x1) {
      return x0.isPlayerConnectionValid(x1);
   }

   // $FF: synthetic method
   static InstanceEntryCallback access$1700(ProxyPlugin x0) {
      return x0.instanceEntryCallback;
   }

   // $FF: synthetic method
   static boolean access$1800(ProxyPlugin x0, OID x1, OID x2, Point x3) {
      return x0.instanceEntryAllowed(x1, x2, x3);
   }

   // $FF: synthetic method
   static void access$1900(ProxyPlugin x0, OID x1, OID x2, OID x3, String x4) {
      x0.updateInstancePerception(x1, x2, x3, x4);
   }

   // $FF: synthetic method
   static int access$1208(ProxyPlugin x0) {
      return x0.instanceEntryCount++;
   }
}
это для какой версии?

кто сможет взяться за аналогичный файлик? разобрать и собрать с редактированием? только версии 10.9
 
посмотри что ожидается в ответе, лень читать это говно. в hosts добавь адес на 127, подними докер контейнер c nginx + fmp и авторизуй себя сам
 
Работает, сам юзаю) какой там фикс, они криворукие
твоя правда, криворукие.
Раз ты тоже юзаешь атавизм, могу у тебя я консультироваться по некоторым вопросам? я новичок в этом деле и просто любитель. но интересно. все ни как не могу нормально реализовать анимации персонажа от третьего лица, все время криво получается и дерганно( Если что в ЛС кину мой дискорд, если вдруг не трудно будет подсказать - может по учить, если не навязчиво то буду благодарен.
 
Назад
Сверху Снизу