package net.scapeemulator.game.model; import net.scapeemulator.game.content.grandexchange.GrandExchange; import net.scapeemulator.game.model.grounditem.GroundItemList; import net.scapeemulator.game.model.npc.NPC; import net.scapeemulator.game.model.object.GroundObjectList; import net.scapeemulator.game.model.pathfinding.ObjectDataListener; import net.scapeemulator.game.model.pathfinding.TraversalMap; import net.scapeemulator.game.model.player.Player; import net.scapeemulator.game.msg.impl.CreateProjectileMessage; import net.scapeemulator.game.msg.impl.PlacementCoordsMessage; import net.scapeemulator.game.net.game.GameSession; import net.scapeemulator.game.task.TaskScheduler; import net.scapeemulator.game.update.PlayerUpdater; /** * Represents our singleton world which can be retrieved by {@link getWorld()}. This contains a * {@link MobList} for {@link Player} and one for {@link Npc}. This contains a * {@link GroundItemList} and a {@link GroundObjectList}. * */ public final class World { public static final int MAX_PLAYERS = 2000; private static final World world = new World(); /** * The world instance. * * @return The world. */ public static World getWorld() { return world; } private final MobList<Player> players = new MobList<>(MAX_PLAYERS); private final MobList<NPC> npcs = new MobList<>(32000); private final TaskScheduler taskScheduler = new TaskScheduler(); private final GrandExchange grandExchange = new GrandExchange(); private final PlayerUpdater updater = new PlayerUpdater(this); private final GroundItemList groundItems = new GroundItemList(); private final GroundObjectList groundObjects = new GroundObjectList(); private final TraversalMap traversalMap = new TraversalMap(); /** * Adds a listener ({@link ObjectDataListener}) to our groundObjects list. */ private World() { /* TODO: Is this in the correct place? */ /* Add the object data listener for the traversal map */ groundObjects.addListener(new ObjectDataListener(traversalMap)); } /** * Gets the {@link MobList} of all Players in this world. * * @return The {@link Player}-s in this {@link World}. */ public MobList<Player> getPlayers() { return players; } /** * Add the npc to our MobList of npcs. * * @param npc The {@link NPC} to add. */ public void addNpc(NPC npc) { npcs.add(npc); } /** * Gets the {@link MobList} of all Npcs in this world. * * @return The {@link NPC}-s in this {@link World}. */ public MobList<NPC> getNpcs() { return npcs; } /** * Gets the {@link GroundItemList} of this world. * * @return The {@link GroundItem}-s in this {@link World}. */ public GroundItemList getGroundItems() { return groundItems; } /** * Gets the {@link GroundObjectList} of this world. * * @return The {@link GroundObject}-s in this {@link World}. */ public GroundObjectList getGroundObjects() { return groundObjects; } /** * Gets the {@link TraversalMap} of this world. * * @return The {@link TraversalMap} of this {@link World}. */ public TraversalMap getTraversalMap() { return traversalMap; } /** * Gets the {@link TaskScheduler} of this world. * * @return The {@link TaskScheduler} in this {@link World}. */ public TaskScheduler getTaskScheduler() { return taskScheduler; } /** * Gets the {@link GrandExchange} of this world. * * @return The {@link GrandExchange} in this {@link World}. */ public GrandExchange getGrandExchange() { return grandExchange; } /** * Performs {@link GameSession#processMessageQueue()} for every { * * @Player in {@link getPlayers()} as well as perform the {@link TaskScheduler#tick()}, * {@link GroundItemList#tick()} & {@link PlayerUpdater#tick()}. */ public void tick() { for (Player player : players) { GameSession session = player.getSession(); if (session != null) { session.processMessageQueue(); } } taskScheduler.tick(); groundItems.tick(); updater.tick(); } public void createGlobalProjectile(Position start, CreateProjectileMessage cpm) { for (Player p : World.getWorld().getPlayers()) { if (!p.getPosition().isWithinScene(start)) { continue; } int localX = start.getX() - p.getPosition().getBaseLocalX(p.getLastKnownRegion().getX() >> 3) - 3; int localY = start.getY() - p.getPosition().getBaseLocalY(p.getLastKnownRegion().getY() >> 3) - 2; p.send(new PlacementCoordsMessage(localX, localY)); p.send(cpm); } } /** * Get a {@link Player} for which {@link Player#getUsername()} or * {@link Player#getDisplayName()} returns username, ignoring the cases. Iterates over {@link * getPlayers()} to find the {@link Player}. * * @param username The String used to find a match. * @return The {@link Player} we found a match for. Null if no match was found. */ public Player getPlayerByName(String username) { for (Player player : players) { if (player.getUsername().equalsIgnoreCase(username) || player.getDisplayName().equalsIgnoreCase(username)) { return player; } } return null; } /** * Get a {@link Player} for which {@link Player#getLongUsername()} returns longName. Iterates * over {@link getPlayers()} to find the {@link Player}. * * @param longName The long used to find a match. * @return The {@link Player} we found a match for. Null if no match was found. */ public Player getPlayerByLongName(long longName) { for (Player player : players) { if (player.getLongUsername() == longName) { return player; } } return null; } /** * Get a {@link Player} associated with the databaseId. Iterates over {@link getPlayers()} and * uses {@link Player#getDatabaseId()}. * * @param id The id to search the associated player with. * @return The player or null if no player was found to be associated with the given id. */ public Player getPlayerByDatabaseId(int id) { for (Player player : players) { if (player.getDatabaseId() == id) { return player; } } return null; } /** * Send the provided text to all players, {@link getPlayers()} using * {@link Player#sendMessage(String text)}. * * @param text The text to send to every player. */ public void sendGlobalMessage(String text) { for (Player player : players) { player.sendMessage(text); } } }