mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-21 09:02:07 -07:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
9288ca7ff7
53 changed files with 1130 additions and 1524 deletions
|
|
@ -10,6 +10,6 @@
|
|||
"WorldTechnicalInformation": {
|
||||
"world_limit": "10",
|
||||
"worldhop_delay": "20000"
|
||||
}
|
||||
|
||||
},
|
||||
"secret_key": "2009scape_development"
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
package ms;
|
||||
|
||||
import ms.classloader.ClassLoadServer;
|
||||
import ms.net.NioReactor;
|
||||
import ms.net.packet.IoBuffer;
|
||||
import ms.net.packet.PacketHeader;
|
||||
import ms.net.packet.WorldPacketRepository;
|
||||
import ms.system.ShutdownSequence;
|
||||
import ms.system.mysql.SQLManager;
|
||||
|
|
@ -100,7 +101,6 @@ public final class Management {
|
|||
new Command("-rlcache", "Reloads launcher/client resource cache") {
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
ClassLoadServer.resetResourceCache();
|
||||
System.out.println("Reloaded resource cache!");
|
||||
}
|
||||
},
|
||||
|
|
@ -118,6 +118,27 @@ public final class Management {
|
|||
player.setWorldId(0);
|
||||
System.out.println("Kicked player " + name + "!");
|
||||
}
|
||||
},
|
||||
|
||||
new Command("-say", "Send a message to all worlds") {
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
String message = String.join(" ", args);
|
||||
message = message.substring(4);
|
||||
for(GameServer server : WorldDatabase.getWorlds()){
|
||||
if(server == null) continue;
|
||||
String finalMessage = message;
|
||||
server.getPlayers().forEach((String uname, PlayerSession p) -> {
|
||||
IoBuffer buffer = new IoBuffer(5, PacketHeader.BYTE);
|
||||
buffer.putString(p.getUsername());
|
||||
buffer.putString("Server");
|
||||
buffer.put(2);
|
||||
buffer.put(2);
|
||||
buffer.putString(finalMessage);
|
||||
p.getWorld().getSession().write(buffer);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -136,7 +157,6 @@ public final class Management {
|
|||
SQLManager.init();
|
||||
//NioReactor.configure(ServerConstants.PORT).start();
|
||||
NioReactor.configure(5555).start();
|
||||
new ClassLoadServer().start();
|
||||
Runtime.getRuntime().addShutdownHook(new ShutdownSequence());
|
||||
System.out.println("Status: ready.");
|
||||
System.out.println("Use -commands for a list of commands!");
|
||||
|
|
|
|||
|
|
@ -29,18 +29,6 @@ public final class ServerConstants {
|
|||
*/
|
||||
public static final OperatingSystem OS = System.getProperty("os.name").toUpperCase().contains("WIN") ? OperatingSystem.WINDOWS : OperatingSystem.UNIX;
|
||||
|
||||
/**
|
||||
* The administrators.
|
||||
*/
|
||||
public static final String[] ADMINISTRATORS = {
|
||||
"redsparr0w",
|
||||
};
|
||||
|
||||
public static final String[] DATABASE_NAMES = {
|
||||
"server",
|
||||
"global",
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops from instantiating.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
package ms.classloader;
|
||||
|
||||
import ms.Management;
|
||||
import ms.ServerConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* ClassLoadServer
|
||||
* @author Clayton Williams (Hope)
|
||||
*/
|
||||
public class ClassLoadServer extends Thread {
|
||||
|
||||
/**
|
||||
* Listening port
|
||||
*/
|
||||
private static final int PORT = 5050;
|
||||
|
||||
/**
|
||||
* serverSocket for incoming connections
|
||||
*/
|
||||
private ServerSocket serverSocket = null;
|
||||
|
||||
/**
|
||||
* Holds classes and resources already added in the server
|
||||
*/
|
||||
protected final static HashMap<String, byte[]> resourceCache = new HashMap<String, byte[]>();
|
||||
|
||||
/**
|
||||
* New socket
|
||||
* @throws UnknownHostException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ClassLoadServer() {
|
||||
try {
|
||||
serverSocket = new ServerSocket(PORT);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Listen for incoming connections
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
resetResourceCache();
|
||||
// System.out.println("Listening on port " + PORT + "...");
|
||||
while (Management.active) {
|
||||
Socket clientSocket = null;
|
||||
try {
|
||||
clientSocket = serverSocket.accept();
|
||||
//System.out.println("New Connection from : " + clientSocket.getInetAddress());
|
||||
WorkerThread wcs = new WorkerThread(clientSocket);
|
||||
wcs.start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads resources recursively from a starting root directory and adds the file bytes to our cache
|
||||
* @param path
|
||||
* @param pathRoot
|
||||
*/
|
||||
private static void loadResources(String path, String pathRoot) {
|
||||
try {
|
||||
path = ServerConstants.fixPath(null, path);
|
||||
pathRoot = ServerConstants.fixPath(null, pathRoot);
|
||||
File root = new File(path);
|
||||
File[] list = root.listFiles();
|
||||
if (list == null) return;
|
||||
for (File f : list) {
|
||||
if (f.isDirectory()) {
|
||||
loadResources(f.getAbsolutePath(), pathRoot);
|
||||
} else {
|
||||
if (f.exists()) {
|
||||
if (!f.getName().startsWith(".")) {
|
||||
byte[] bytes = Files.readAllBytes(f.toPath());
|
||||
String name = ServerConstants.fixPath(null, f.getAbsolutePath().substring(f.getAbsolutePath().lastIndexOf(pathRoot)));
|
||||
//System.out.println("[ClassLoadServer] Loaded resource '" + f.getName() +
|
||||
// "' Size: " + NumberFormat.getInstance().format(bytes.length) + " bytes");
|
||||
resourceCache.put(name, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the class cache and loads resources
|
||||
*/
|
||||
public static void resetResourceCache() {
|
||||
resourceCache.clear();
|
||||
//loadResources("bin/org/keldagrim/launcher/", "org/arios/launcher/");
|
||||
//loadResources("resources/", "org/keldagrim/launcher/");
|
||||
//System.out.println("Loaded all resources!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
package ms.classloader;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.Map;
|
||||
|
||||
import ms.ServerConstants;
|
||||
import ms.system.OperatingSystem;
|
||||
|
||||
/**
|
||||
* Worker thread for launcher connections
|
||||
* @author Clayton Williams (Hope)
|
||||
*
|
||||
*/
|
||||
public class WorkerThread extends Thread {
|
||||
|
||||
/**
|
||||
* Our launcher connection
|
||||
*/
|
||||
private Socket launcher = null;
|
||||
|
||||
/**
|
||||
* Input stream from launcher
|
||||
*/
|
||||
private ObjectInputStream is = null;
|
||||
|
||||
/**
|
||||
* Output stream to launcher
|
||||
*/
|
||||
private ObjectOutputStream os = null;
|
||||
|
||||
/**
|
||||
* The user's operating system type
|
||||
*/
|
||||
private OperatingSystem operatingSystem = OperatingSystem.WINDOWS;
|
||||
|
||||
/**
|
||||
* Creates a new worker thread to handle the launcher requests
|
||||
* @param socket
|
||||
* @param classesCache
|
||||
* @throws IOException
|
||||
*/
|
||||
public WorkerThread(Socket launcher) throws IOException {
|
||||
super();
|
||||
this.launcher = launcher;
|
||||
try {
|
||||
os = new ObjectOutputStream(new BufferedOutputStream(this.launcher.getOutputStream()));
|
||||
os.flush();
|
||||
is = new ObjectInputStream(new BufferedInputStream(launcher.getInputStream()));
|
||||
} catch (IOException ioe) {
|
||||
this.launcher.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Input Stream handler
|
||||
*/
|
||||
@SuppressWarnings("unused") //saving resource type for later
|
||||
public void run() {
|
||||
byte opcode = -1;
|
||||
try {
|
||||
while (true) {
|
||||
opcode = is.readByte();
|
||||
switch(opcode) {
|
||||
case 1: //requests revision
|
||||
operatingSystem = is.readUTF().contains("UNIX") ? OperatingSystem.UNIX : OperatingSystem.WINDOWS;
|
||||
os.reset();
|
||||
os.writeInt(ClassLoadServer.resourceCache.size());//#customresources
|
||||
for (Map.Entry<String, byte[]> hm : ClassLoadServer.resourceCache.entrySet()) {
|
||||
os.writeUTF(ServerConstants.fixPath(operatingSystem, (String) hm.getKey()));
|
||||
os.writeInt(hm.getValue().length);
|
||||
}
|
||||
os.writeByte(1); //number of custom resources
|
||||
//followed by 2 strings
|
||||
//System.err.println(operatingSystem.name());
|
||||
os.writeUTF(ServerConstants.fixPath(operatingSystem, "ms/launcher/arios-gamepack-530.jar"));
|
||||
os.writeUTF("BINARY");
|
||||
os.flush();
|
||||
break;
|
||||
case 2: //resource request
|
||||
String resourceName = ServerConstants.fixPath(null, is.readUTF());
|
||||
String resourceType = is.readUTF();
|
||||
if (ClassLoadServer.resourceCache.containsKey(resourceName)) {
|
||||
sendResource(ClassLoadServer.resourceCache.get(resourceName));
|
||||
//System.out.println("Sent Resource: " + resourceName);
|
||||
} else {
|
||||
sendOpcode(-1);
|
||||
//System.out.println("Could not send resource '" + resourceName + "'");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unhandled opcode=" + opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
//System.out.println("Client force disconnect.");
|
||||
} finally {
|
||||
try {
|
||||
is.close();
|
||||
os.close();
|
||||
launcher.close();
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* send a byte array packet to the client
|
||||
* @exception IOException file read error.
|
||||
*/
|
||||
protected void sendResource(byte [] bytes) throws IOException {
|
||||
os.reset();
|
||||
os.writeByte(2);
|
||||
os.writeInt(bytes.length);
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
os.writeByte(bytes[i]);
|
||||
}
|
||||
os.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send no data opcodes
|
||||
* @param opcode
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void sendOpcode(int opcode) throws IOException {
|
||||
os.reset();
|
||||
os.writeByte(opcode);
|
||||
os.flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -67,6 +67,10 @@ public final class IoEventHandler {
|
|||
ByteBuffer buffer = ByteBuffer.allocate(100_000);
|
||||
IoSession session = (IoSession) key.attachment();
|
||||
if (channel.read(buffer) == -1) {
|
||||
if(session == null){
|
||||
key.cancel();
|
||||
return;
|
||||
}
|
||||
if(session.getGameServer() != null){
|
||||
WorldDatabase.unRegister(session.getGameServer());
|
||||
}
|
||||
|
|
@ -87,8 +91,10 @@ public final class IoEventHandler {
|
|||
*/
|
||||
public void write(SelectionKey key) {
|
||||
IoSession session = (IoSession) key.attachment();
|
||||
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
|
||||
session.write();
|
||||
if(session != null) {
|
||||
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
|
||||
session.write();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -168,9 +168,9 @@ public class IoSession {
|
|||
}
|
||||
writingQueue.remove(0);
|
||||
}
|
||||
writingLock.unlock();
|
||||
} catch (IOException e) {
|
||||
disconnect();
|
||||
} finally {
|
||||
writingLock.unlock();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ public final class NioReactor implements Runnable {
|
|||
SelectionKey key = keys.next();
|
||||
keys.remove();
|
||||
try {
|
||||
if(key == null) continue;
|
||||
if (!key.isValid() || !key.channel().isOpen()) {
|
||||
key.cancel();
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import ms.net.IoReadEvent;
|
||||
import ms.net.IoSession;
|
||||
import ms.system.util.ManagementConstants;
|
||||
import ms.world.WorldDatabase;
|
||||
import ms.system.util.ByteBufferUtils;
|
||||
|
||||
|
|
@ -12,11 +13,6 @@ import ms.system.util.ByteBufferUtils;
|
|||
* @author Emperor
|
||||
*/
|
||||
public final class HSReadEvent extends IoReadEvent {
|
||||
|
||||
/**
|
||||
* The password used to verify
|
||||
*/
|
||||
private static final String PASSWORD = "0x14ari0SSbh98989910";
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HSReadEvent}.
|
||||
|
|
@ -33,7 +29,7 @@ public final class HSReadEvent extends IoReadEvent {
|
|||
switch (opcode) {
|
||||
case 88:
|
||||
String password = ByteBufferUtils.getString(buffer);
|
||||
if (!password.equals(PASSWORD)) {
|
||||
if (!password.equals(ManagementConstants.getSECRET_KEY())) {
|
||||
System.out.println("Password mismatch (attempt=" + password + ")!");
|
||||
session.disconnect();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -547,7 +547,7 @@ public class IoBuffer {
|
|||
long second = getIntB();
|
||||
if (second < 0)
|
||||
second = second & 0xffffffffL;
|
||||
return (first << -41780448) + second;
|
||||
return (first << 32) + second;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -567,7 +567,7 @@ public class IoBuffer {
|
|||
if (peek <= Short.MAX_VALUE) {
|
||||
return buf.getShort() & 0xFFFF;
|
||||
}
|
||||
return (buf.getInt() & 0xFFFFFFFF) - 32768;
|
||||
return buf.getInt() - 32768;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import ms.system.PunishmentStorage
|
|||
import ms.system.communication.ClanRank
|
||||
import ms.system.communication.ClanRepository
|
||||
import ms.system.communication.CommunicationInfo
|
||||
import ms.system.util.ManagementConstants.Companion.WORLD_HOP_DELAY
|
||||
import ms.system.util.ManagementConstants.WORLD_HOP_DELAY
|
||||
import ms.world.GameServer
|
||||
import ms.world.PlayerSession
|
||||
import ms.world.WorldDatabase
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public final class PunishmentStorage {
|
|||
return;
|
||||
}
|
||||
long end = Long.MAX_VALUE;
|
||||
if (duration != -1l && duration != 0L) {
|
||||
if (duration != -1L && duration != 0L) {
|
||||
end = System.currentTimeMillis() + duration;
|
||||
} else if (duration == 0L) {
|
||||
end = 0L;
|
||||
|
|
|
|||
|
|
@ -12,10 +12,7 @@ import java.nio.ByteBuffer;
|
|||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
|
|
@ -184,9 +181,7 @@ public final class CommunicationInfo {
|
|||
String bl = set.getString("blocked");
|
||||
if (bl != null && !bl.isEmpty()) {
|
||||
tokens = bl.split(",");
|
||||
for (String name : tokens) {
|
||||
blocked.add(name);
|
||||
}
|
||||
blocked.addAll(Arrays.asList(tokens));
|
||||
}
|
||||
clanName = set.getString("clanName");
|
||||
currentClan = set.getString("currentClan");
|
||||
|
|
@ -236,6 +231,9 @@ public final class CommunicationInfo {
|
|||
case 2:
|
||||
tradeSetting = Integer.parseInt(tokens[2]);
|
||||
break;
|
||||
default:
|
||||
System.out.println("Illegal arg count in chatsetting string: " + chatSettings);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package ms.system.mysql
|
||||
|
||||
import ms.system.util.ManagementConstants
|
||||
import ms.system.util.ManagementConstants.Companion.DATABASE_HOST_ADDRESS
|
||||
import ms.system.util.ManagementConstants.Companion.DATABASE_NAME
|
||||
import ms.system.util.ManagementConstants.Companion.DATABASE_PASSWORD
|
||||
import ms.system.util.ManagementConstants.Companion.DATABASE_PORT
|
||||
import ms.system.util.ManagementConstants.Companion.DATABASE_USERNAME
|
||||
import ms.system.util.ManagementConstants.DATABASE_HOST_ADDRESS
|
||||
import ms.system.util.ManagementConstants.DATABASE_NAME
|
||||
import ms.system.util.ManagementConstants.DATABASE_PASSWORD
|
||||
import ms.system.util.ManagementConstants.DATABASE_PORT
|
||||
import ms.system.util.ManagementConstants.DATABASE_USERNAME
|
||||
import java.sql.Connection
|
||||
import java.sql.DriverManager
|
||||
import java.sql.SQLException
|
||||
|
|
|
|||
|
|
@ -30,19 +30,20 @@ class ManagementConfigParser(path: String) {
|
|||
data = parser.parse(reader) as JSONObject
|
||||
parseDatabaseInformation()
|
||||
parseWorldTechnicalSettings()
|
||||
ManagementConstants.SECRET_KEY = data!!["secret_key"].toString()
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseDatabaseInformation(){
|
||||
data ?: return
|
||||
val dbData = data!!["DatabaseInformation"] as JSONObject
|
||||
ManagementConstants().parseDBProp(dbData)
|
||||
ManagementConstants.parseDBProp(dbData)
|
||||
}
|
||||
|
||||
private fun parseWorldTechnicalSettings(){
|
||||
data ?: return
|
||||
val wtiData = data!!["WorldTechnicalInformation"] as JSONObject
|
||||
ManagementConstants().parseWTIProp(wtiData)
|
||||
ManagementConstants.parseWTIProp(wtiData)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,32 +2,31 @@ package ms.system.util
|
|||
|
||||
import org.json.simple.JSONObject
|
||||
|
||||
class ManagementConstants {
|
||||
object ManagementConstants {
|
||||
|
||||
companion object {
|
||||
//MySQL main database name
|
||||
var DATABASE_NAME: String = "global"
|
||||
|
||||
//MySQL main database name
|
||||
var DATABASE_NAME: String = "global"
|
||||
//MySQL database username
|
||||
var DATABASE_USERNAME: String = "root"
|
||||
|
||||
//MySQL database username
|
||||
var DATABASE_USERNAME: String = "root"
|
||||
//MySQL database password
|
||||
var DATABASE_PASSWORD: String = ""
|
||||
|
||||
//MySQL database password
|
||||
var DATABASE_PASSWORD: String = ""
|
||||
//MySQL host
|
||||
var DATABASE_HOST_ADDRESS: String = "127.0.0.1"
|
||||
|
||||
//MySQL host
|
||||
var DATABASE_HOST_ADDRESS: String = "127.0.0.1"
|
||||
//MySQL port
|
||||
var DATABASE_PORT: Int = 3306
|
||||
|
||||
//MySQL port
|
||||
var DATABASE_PORT: Int = 3306
|
||||
//Max amount of worlds supported on the world list
|
||||
var MAX_WORLD_AMOUNT: Int = 10
|
||||
|
||||
//Max amount of worlds supported on the world list
|
||||
var MAX_WORLD_AMOUNT: Int = 10
|
||||
//User world hop delay in seconds
|
||||
var WORLD_HOP_DELAY: Long = 20_000L
|
||||
|
||||
//User world hop delay in seconds
|
||||
var WORLD_HOP_DELAY: Long = 20_000L
|
||||
|
||||
}
|
||||
@JvmStatic
|
||||
var SECRET_KEY: String = ""
|
||||
|
||||
fun parseDBProp(data: JSONObject) {
|
||||
DATABASE_NAME = data["database_name"].toString()
|
||||
|
|
|
|||
|
|
@ -409,8 +409,9 @@ public final class StringUtils {
|
|||
}
|
||||
}
|
||||
}
|
||||
return -i_26_ + ((7 + i_30_) >> -662855293);
|
||||
return -i_26_ + ((7 + i_30_) >> 3);
|
||||
} catch (RuntimeException runtimeexception) {
|
||||
runtimeexception.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public final class PlayerSession {
|
|||
/**
|
||||
* The time stamp of last disconnection.
|
||||
*/
|
||||
private long disconnectionTime = 0l;
|
||||
private long disconnectionTime = 0L;
|
||||
|
||||
/**
|
||||
* How long the player is banned for.
|
||||
|
|
@ -463,11 +463,8 @@ public final class PlayerSession {
|
|||
this.disconnectionTime = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof PlayerSession) {
|
||||
return username.equals(((PlayerSession) o).username);
|
||||
} else return false;
|
||||
public boolean equalsSession(PlayerSession o){
|
||||
return username.equals(o.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ import java.util.*
|
|||
|
||||
object MSLogger {
|
||||
val t = Terminal()
|
||||
val formatter = SimpleDateFormat("HH:mm:ss")
|
||||
var tradeLog: Writer? = null
|
||||
var tradeLogWriter: BufferedWriter? = null
|
||||
|
||||
|
||||
fun getTime(): String{
|
||||
val formatter = SimpleDateFormat("HH:mm:ss")
|
||||
return "[" + formatter.format(Date(System.currentTimeMillis())) +"]"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62771,7 +62771,7 @@
|
|||
{
|
||||
"default": [],
|
||||
"charm": [],
|
||||
"ids": "428, 429",
|
||||
"ids": "428,429",
|
||||
"description": "Shade (Stronghold of Security) (So Shade Robes can drop)",
|
||||
"main": [
|
||||
{
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -100,6 +100,7 @@ public abstract class CutscenePlugin extends ActivityPlugin {
|
|||
unpause();
|
||||
}
|
||||
player.unlock();
|
||||
player.getInterfaceManager().openDefaultTabs();
|
||||
player.getWalkingQueue().reset();
|
||||
player.getLocks().unlockMovement();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package core.game.content.activity.guild;
|
||||
|
||||
import api.ContentAPI;
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.cache.def.impl.SceneryDefinition;
|
||||
import core.game.content.dialogue.DialoguePlugin;
|
||||
|
|
@ -60,7 +61,7 @@ public final class WizardGuildPlugin extends OptionHandler {
|
|||
switch (id) {
|
||||
case 1600:
|
||||
case 1601:
|
||||
if (player.getSkills().getStaticLevel(Skills.MAGIC) < 66) {
|
||||
if (ContentAPI.getDynLevel(player, Skills.MAGIC) < 66) {
|
||||
player.getDialogueInterpreter().sendDialogue("You need a Magic level of at least 66 to enter.");
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,219 +0,0 @@
|
|||
package core.game.content.dialogue;
|
||||
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.plugin.Initializable;
|
||||
import core.game.world.map.Location;
|
||||
|
||||
/**
|
||||
* Represents the dialogue plugin used for Bill Teach
|
||||
* @author Charlie
|
||||
* @version 1.0
|
||||
*/
|
||||
@Initializable
|
||||
public final class BillTeachDialogue extends DialoguePlugin {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BarfyBill} {@code Object}.
|
||||
*/
|
||||
public BillTeachDialogue() {
|
||||
/**
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BarfyBill} {@code Object}.
|
||||
* @param player the player.
|
||||
*/
|
||||
public BillTeachDialogue(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialoguePlugin newInstance(Player player) {
|
||||
return new BillTeachDialogue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean open(Object... args) {
|
||||
npc = new NPC(3155);
|
||||
player("Hello there.");
|
||||
stage = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
npc("Arr'! Avast ye' scallywag!", "You be lookin' to get somewhere " + (player.isMale() ? "lad?" : "lass?"));
|
||||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
interpreter.sendOptions("Select an Option", "Yes", "No, thank you");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
player("Yes, where can you take me?");
|
||||
stage = 1000;
|
||||
break;
|
||||
case 2:
|
||||
npc("Arr'! You be wastin' my time again..");
|
||||
stage = 7;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1000:
|
||||
npc("Aye, take a browse through me options.");
|
||||
stage++;
|
||||
break;
|
||||
case 1001:
|
||||
interpreter.sendOptions("Select an Option", "Slayer Tower", "Zanaris Fairy Ring", "Gnome Stronghold", "Rellekka", "More");
|
||||
stage = 2000;
|
||||
break;
|
||||
case 2000:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
if(!player.getQuestRepository().isComplete("Priest in Peril")) {
|
||||
npc("Aye, sorry there " + pirateGender() + ", but you'll be needing to ", "help King Roald with something first.");
|
||||
stage = 7;
|
||||
} else {
|
||||
end();
|
||||
player.teleport(new Location(3429, 3526, 0));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(!player.getQuestRepository().isComplete("Lost City")) {
|
||||
npc("Aye, sorry there " + pirateGender() + ", but you'll be needing to ", "discover Zanaris first.");
|
||||
stage = 7;
|
||||
} else {
|
||||
end();
|
||||
player.teleport(new Location(2412, 4433, 0));
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
end();
|
||||
player.teleport(new Location(2461, 3444, 0));
|
||||
break;
|
||||
case 4:
|
||||
end();
|
||||
player.teleport(new Location(2669, 3631, 0));
|
||||
break;
|
||||
case 5:
|
||||
interpreter.sendOptions("Select an Option", "Kalphite Lair", "Asgarnian Ice Dungeon", "Fremmenik Dungeon", "Taverley Dungeon", "More");
|
||||
stage = 3000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3000:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
end();
|
||||
player.teleport(new Location(3227, 3107, 0));
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
player.teleport(new Location(3007, 9550, 0));
|
||||
break;
|
||||
case 3:
|
||||
end();
|
||||
player.teleport(new Location(2808, 10002, 0));
|
||||
break;
|
||||
case 4:
|
||||
end();
|
||||
player.teleport(new Location(2884, 9798, 0));
|
||||
break;
|
||||
case 5:
|
||||
interpreter.sendOptions("Select an Option", "Waterfall Dungeon", "Brimhaven Dungeon", "Ape Atoll Dungeon", "God Wars Dungeon", "More");
|
||||
stage = 4000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4000:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
end();
|
||||
player.teleport(new Location(2575, 9861, 0));
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
player.teleport(new Location(2713, 9564, 0));
|
||||
break;
|
||||
case 3:
|
||||
end();
|
||||
player.teleport(new Location(2715, 9184, 0));
|
||||
break;
|
||||
case 4:
|
||||
end();
|
||||
player.teleport(new Location(2898, 3710, 0));
|
||||
break;
|
||||
case 5:
|
||||
interpreter.sendOptions("Select an Option", "Shilo Village", "Yanille", "Zul-Andra", "Piscatoris Fishing Colony", "More");
|
||||
stage = 5000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5000:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
end();
|
||||
player.teleport(new Location(2867, 2952, 0));
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
player.teleport(new Location(2544, 3096, 0));
|
||||
break;
|
||||
case 3:
|
||||
end();
|
||||
player.teleport(new Location(2193, 3055, 0));
|
||||
break;
|
||||
case 4:
|
||||
end();
|
||||
player.teleport(new Location(2343, 3663, 0));
|
||||
break;
|
||||
case 5:
|
||||
interpreter.sendOptions("Select an Option", "Bandit Camp", "Miscellenia", "Mort'ton", "Feldip Hills", "Back");
|
||||
stage = 6000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6000:
|
||||
switch (buttonId) {
|
||||
case 1:
|
||||
end();
|
||||
player.teleport(new Location(3176, 2987, 0));
|
||||
break;
|
||||
case 2:
|
||||
end();
|
||||
player.teleport(new Location(2581, 3845, 0));
|
||||
break;
|
||||
case 3:
|
||||
end();
|
||||
player.teleport(new Location(3488, 3296, 0));
|
||||
break;
|
||||
case 4:
|
||||
end();
|
||||
player.teleport(new Location(2525, 2915, 0));
|
||||
break;
|
||||
case 5:
|
||||
interpreter.sendOptions("Select an Option", "Slayer Tower", "Zanaris Fairy Ring", "Gnome Stronghold", "Rellekka", "More");
|
||||
stage = 2000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
end();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIds() {
|
||||
return new int[] { 3155 };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -137,7 +137,7 @@ public final class HansDialoguePlugin extends DialoguePlugin {
|
|||
case 12:
|
||||
switch(buttonId){
|
||||
case 1:
|
||||
options("1.0x","2.5x","10x","20x");
|
||||
options("1.0x","2.5x","Stay 5.0x");
|
||||
stage++;
|
||||
break;
|
||||
case 2:
|
||||
|
|
@ -166,13 +166,9 @@ public final class HansDialoguePlugin extends DialoguePlugin {
|
|||
}
|
||||
break;
|
||||
case 3:
|
||||
player.getSkills().experienceMutiplier = 10.0;
|
||||
stage = 14;
|
||||
break;
|
||||
case 4:
|
||||
player.getSkills().experienceMutiplier = 20.0;
|
||||
stage = 14;
|
||||
break;
|
||||
playerl(FacialExpression.FRIENDLY, "I'd rather stay 5x, thank you.");
|
||||
stage = END_DIALOGUE;
|
||||
return true;
|
||||
}
|
||||
npc("One moment, please...");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ public final class SimonTempleton extends DialoguePlugin{
|
|||
return true;
|
||||
}
|
||||
}
|
||||
player.getPacketDispatch().sendMessage("" + args.length);
|
||||
npc("G'day, mate!. Got any new", "pyramid artefacts for me?");
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,913 +0,0 @@
|
|||
package core.game.content.global.shop;
|
||||
|
||||
import api.ContentAPI;
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.game.container.Container;
|
||||
import core.game.container.ContainerType;
|
||||
import org.rs09.consts.Items;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.diary.DiaryType;
|
||||
import core.game.node.item.Item;
|
||||
import rs09.game.system.SystemLogger;
|
||||
import rs09.game.system.config.ItemConfigParser;
|
||||
import rs09.game.world.GameWorld;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class representing a shop.
|
||||
*
|
||||
* @author 'Vexia
|
||||
* @author Jamix77
|
||||
*/
|
||||
public class Shop {
|
||||
|
||||
/**
|
||||
* Represents the general store items.
|
||||
*/
|
||||
public final static Item[] GENERAL_STORE_ITEMS = new Item[]{
|
||||
new Item(Items.EMPTY_POT_1931,5),
|
||||
new Item(Items.JUG_1935,5),
|
||||
new Item(Items.SHEARS_1735,2),
|
||||
new Item(Items.BUCKET_1925,3),
|
||||
new Item(Items.BOWL_1923,2),
|
||||
new Item(Items.CAKE_TIN_1887,2),
|
||||
new Item(Items.TINDERBOX_590,2),
|
||||
new Item(Items.CHISEL_1755,2),
|
||||
new Item(Items.HAMMER_2347,5),
|
||||
new Item(Items.NEWCOMER_MAP_550,5),
|
||||
new Item(Items.SECURITY_BOOK_9003,5)
|
||||
};
|
||||
/**
|
||||
* Represents the coins item.
|
||||
*/
|
||||
private static final int COINS = 995;
|
||||
/**
|
||||
* Represents the tokkul item id.
|
||||
*/
|
||||
private static final int TOKKUL = 6529;
|
||||
|
||||
/**
|
||||
* Represents the archery ticket item id
|
||||
*/
|
||||
private static final int ARCHERY_TICKET = 1464;
|
||||
|
||||
/**
|
||||
* Represents the shop containers.
|
||||
*/
|
||||
private final Container[] containers = new Container[]{new Container(40, ContainerType.SHOP), new Container(40, ContainerType.SHOP)};
|
||||
/**
|
||||
* Represents the list of shop viewers.
|
||||
*/
|
||||
private final List<ShopViewer> viewers = new ArrayList<>(20);
|
||||
|
||||
/**
|
||||
* Represents the title of the shop.
|
||||
*/
|
||||
private final String title;
|
||||
|
||||
/**
|
||||
* Represents the items in the store.
|
||||
*/
|
||||
private Item[] items;
|
||||
|
||||
/**
|
||||
* Represents if it's a general store.
|
||||
*/
|
||||
private final boolean general;
|
||||
|
||||
/**
|
||||
* Represents the currency the shop allows.
|
||||
*/
|
||||
private final int currency;
|
||||
|
||||
/**
|
||||
* If the shop buys for high alch.
|
||||
*/
|
||||
private final boolean highAlch;
|
||||
|
||||
/**
|
||||
* Sell price for all shop items, if needed.
|
||||
*/
|
||||
private int sellAllFor;
|
||||
|
||||
/**
|
||||
* The last restock.
|
||||
*/
|
||||
private int lastRestock;
|
||||
|
||||
/**
|
||||
* If the shop should restock.
|
||||
*/
|
||||
private boolean restock;
|
||||
|
||||
/**
|
||||
* If it's a point shop.
|
||||
*/
|
||||
private boolean pointShop;
|
||||
|
||||
/**
|
||||
* The npcs of the shop.
|
||||
*/
|
||||
private int[] npcs;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param items the items.
|
||||
* @param general the general.
|
||||
* @param currency the currency.
|
||||
* @param highAlch if high alch.
|
||||
*/
|
||||
public Shop(String title, Item[] items, boolean general, int currency, boolean highAlch) {
|
||||
this.title = title;
|
||||
this.items = items;
|
||||
this.general = general;
|
||||
this.currency = currency;
|
||||
this.highAlch = highAlch;
|
||||
this.getContainer(0).add(items);
|
||||
this.setRestock(true);
|
||||
lastRestock = GameWorld.getTicks() + 100;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param items the items.
|
||||
* @param general the general.
|
||||
* @param currency the currency.
|
||||
* @param highAlch if high alch.
|
||||
* @param restock if restock.
|
||||
*/
|
||||
public Shop(String title, Item[] items, boolean general, int currency, boolean highAlch, boolean restock, int sellAllFor) {
|
||||
this(title, items, general, currency, highAlch);
|
||||
this.sellAllFor = sellAllFor;
|
||||
this.setRestock(restock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}
|
||||
*
|
||||
* @param title the shop title
|
||||
* @param items items the shop can handle
|
||||
* @param general is this a general store
|
||||
* @param currency what currency is used
|
||||
*/
|
||||
public Shop(String title, Item[] items, int[] npcs, boolean general, int currency) {
|
||||
this(title, items, general, currency, false);
|
||||
this.setNpcs(npcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param items the items.
|
||||
* @param general the general.
|
||||
*/
|
||||
public Shop(String title, Item[] items, boolean general) {
|
||||
this(title, items, general, COINS, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param general the general.
|
||||
*/
|
||||
public Shop(String title, boolean general) {
|
||||
this(title, GENERAL_STORE_ITEMS, general);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param general the general.
|
||||
* @param highAlch if highAlch.
|
||||
*/
|
||||
public Shop(String title, boolean general, boolean highAlch) {
|
||||
this(title, GENERAL_STORE_ITEMS, general, COINS, highAlch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param general the general.
|
||||
* @param highAlch if highAlch.
|
||||
*/
|
||||
public Shop(String title, boolean general, int currency, boolean highAlch) {
|
||||
this(title, GENERAL_STORE_ITEMS, general, currency, highAlch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param items the items.
|
||||
* @param npcs the npcs.
|
||||
* @param general the general.
|
||||
*/
|
||||
public Shop(String title, Item[] items, int[] npcs, boolean general) {
|
||||
this(title, items, general, COINS, false);
|
||||
this.setNpcs(npcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param npcs the npcs.
|
||||
* @param general the general.
|
||||
*/
|
||||
public Shop(String title, int[] npcs, boolean general) {
|
||||
this(title, GENERAL_STORE_ITEMS, npcs, general);
|
||||
this.setNpcs(npcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Shop} {@code Object}.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param npcs the npcs.
|
||||
* @param general the general.
|
||||
* @param highAlch if highAlch.
|
||||
*/
|
||||
public Shop(String title, int[] npcs, boolean general, boolean highAlch) {
|
||||
this(title, GENERAL_STORE_ITEMS, general, 995, highAlch);
|
||||
this.setNpcs(npcs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to open the shop.
|
||||
*
|
||||
* @param player the shop.
|
||||
*/
|
||||
public void open(final Player player) {
|
||||
ShopViewer.extend(player, this).open();
|
||||
|
||||
// Browse the Lumbridge General Store
|
||||
if (getTitle().equalsIgnoreCase("Lumbridge General Store")) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 0, 18);
|
||||
}
|
||||
|
||||
// Browse through Oziach's Armour Shop
|
||||
if (getTitle().equalsIgnoreCase("Oziach's Armour")) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.VARROCK, 1, 20);
|
||||
}
|
||||
}
|
||||
|
||||
public void give(Player player, final int slot, int amount, int tabIndex) {
|
||||
final Container container = getContainer(tabIndex);
|
||||
final Item item = container.get(slot);
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
final Item add = new Item(item.getId(), amount);
|
||||
if (add.getAmount() < 1 || !player.getInventory().hasSpaceFor(add)) {
|
||||
player.getPacketDispatch().sendMessage("You have no inventory space at the moment and cannot get anything.");
|
||||
return;
|
||||
}
|
||||
add.setAmount(getAmount(player, add));
|
||||
if (add.getAmount() < 1 || !player.getInventory().hasSpaceFor(add)) {
|
||||
player.getPacketDispatch().sendMessage("You have no inventory space at the moment and cannot get anything.");
|
||||
return;
|
||||
}
|
||||
player.getInventory().add(add);
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to buy an item from the shop.
|
||||
*
|
||||
* @param slot the slot.
|
||||
* @param amount the amount.
|
||||
*/
|
||||
public void buy(Player player, final int slot, int amount, int tabIndex) {
|
||||
if (tabIndex == 1 && player.getIronmanManager().checkRestriction()) {
|
||||
return;
|
||||
}
|
||||
final Container container = getContainer(tabIndex);
|
||||
final Item item = container.get(slot);
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
if (item.getAmount() == 0) {
|
||||
player.getPacketDispatch().sendMessage("There is no stock of that item at the moment.");
|
||||
return;
|
||||
}
|
||||
if (amount > item.getAmount() && !(item.getAmount() == -1)) {
|
||||
amount = item.getAmount();
|
||||
}
|
||||
final Item add = new Item(item.getId(), amount);
|
||||
if (player.getInventory().getMaximumAdd(add) < amount) {
|
||||
add.setAmount(player.getInventory().getMaximumAdd(add));
|
||||
}
|
||||
if (add.getAmount() < 1 || !player.getInventory().hasSpaceFor(add)) {
|
||||
player.getPacketDispatch().sendMessage("You have no inventory space at the moment and cannot buy anything.");
|
||||
return;
|
||||
}
|
||||
add.setAmount(getAmount(player, add));
|
||||
if (add.getAmount() < 1 || !player.getInventory().hasSpaceFor(add)) {
|
||||
player.getPacketDispatch().sendMessage("You have no inventory space at the moment and cannot buy anything.");
|
||||
return;
|
||||
}
|
||||
int price = add.getAmount() * getBuyPrice(item, player);
|
||||
final Item currency = new Item(getCurrency(), price);
|
||||
if (!canBuy(player, item, price, currency)) {
|
||||
return;
|
||||
}
|
||||
if (handleBuy(player, currency)) {
|
||||
if (pointShop) {
|
||||
decrementPoints(player, price);
|
||||
}
|
||||
if (tabIndex == 0) {
|
||||
if(!(container.getAmount(item) == -1))
|
||||
container.replace(new Item(item.getId(), container.getAmount(item) - add.getAmount()), slot, true);
|
||||
} else {
|
||||
container.remove(add);
|
||||
container.shift();
|
||||
}
|
||||
|
||||
// Achievement Diary Handlers
|
||||
if (add.getId() == Items.BLACK_CHAINBODY_1107 && getTitle().equalsIgnoreCase("Wayne's Chains") && !player.getAttribute("diary:falador:black-chain-bought", false)) {
|
||||
player.setAttribute("/save:diary:falador:black-chain-bought", true);
|
||||
}
|
||||
if (add.getId() == 12622 && getTitle().equalsIgnoreCase("Sarah's Farming Shop")) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.FALADOR, 0, 0);
|
||||
}
|
||||
if (add.getId() == Items.CANDLE_36 && getTitle().equalsIgnoreCase("Candle Shop")) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 0, 9);
|
||||
}
|
||||
if (getTitle().equalsIgnoreCase("Ranging Guild Ticket Exchange")) {
|
||||
player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 8);
|
||||
}
|
||||
|
||||
player.getInventory().add(add);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to sell an item to the shop.
|
||||
*
|
||||
* @param slot the slot.
|
||||
* @param amount the amount.
|
||||
*/
|
||||
public void sell(Player player, final int slot, int amount, int tabIndex) {
|
||||
final Item item = player.getInventory().get(slot);
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
final ItemDefinition def = ItemDefinition.forId(item.getId());
|
||||
if (!canSell(player, item, def)) {
|
||||
return;
|
||||
}
|
||||
final Container container = getContainer(item);
|
||||
if (amount > player.getInventory().getAmount(item)) {
|
||||
amount = player.getInventory().getAmount(item);
|
||||
}
|
||||
Item add = new Item(item.getId(), amount);
|
||||
if (add.getAmount() > container.getMaximumAdd(add)) {
|
||||
add.setAmount(container.getMaximumAdd(add));
|
||||
}
|
||||
player.debug("" + add.getAmount());
|
||||
if (!container.hasSpaceFor(add) || add.getAmount() < 1) {
|
||||
player.getPacketDispatch().sendMessage("The shop has ran out of space.");
|
||||
return;
|
||||
}
|
||||
final Item currency = new Item(getCurrency(), getSellingValue(add, player));
|
||||
if(item.getDefinition().isStackable()){
|
||||
if (!player.getInventory().hasSpaceFor(currency)) {
|
||||
player.getPacketDispatch().sendMessage("You don't have enough space for that many " + currency.getName().toLowerCase() + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
player.debug("Selling item");
|
||||
if (player.getInventory().remove(add, slot, true)) {
|
||||
if (currency.getAmount() > player.getInventory().getMaximumAdd(currency)) {
|
||||
currency.setAmount(player.getInventory().getMaximumAdd(currency));
|
||||
}
|
||||
if (!add.getDefinition().isUnnoted()) {
|
||||
add = new Item(add.getNoteChange(), add.getAmount());
|
||||
}
|
||||
if (container.getAmount(add.getId()) == -1 || container.add(add)) {
|
||||
if (currency.getAmount() > 0) {
|
||||
player.debug("Adding coins to inventory");
|
||||
player.getInventory().add(currency);
|
||||
}
|
||||
final ShopViewer viewer = player.getExtension(ShopViewer.class);
|
||||
tabIndex = container == getContainers()[0] ? 0 : 1;
|
||||
sendStock(player, tabIndex);
|
||||
if (viewer != null) {
|
||||
viewer.setTabIndex(tabIndex);
|
||||
}
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Values an item.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param viewer the viewer.
|
||||
* @param item the item.
|
||||
* @param sell the sell.
|
||||
*/
|
||||
public void value(Player player, ShopViewer viewer, Item item, boolean sell) {
|
||||
if (sell) {
|
||||
if (pointShop || item.getId() == viewer.getShop().getCurrency() || !item.getDefinition().isTradeable() || !viewer.getShop().itemAllowed(item.getId())) {
|
||||
player.getPacketDispatch().sendMessage("You can't sell this item.");
|
||||
return;
|
||||
}
|
||||
final int value = viewer.getShop().getSellingValue(new Item(item.getId(), 1), player);
|
||||
String currency = pointShop ? getPointsName() : ItemDefinition.forId(viewer.getShop().getCurrency()).getName().toLowerCase();
|
||||
if (value == 1 && currency.charAt(currency.length() - 1) == 's') {
|
||||
currency = currency.substring(0, currency.length() - 1);
|
||||
}
|
||||
player.getPacketDispatch().sendMessage(item.getName() + ": shop will buy for " + value + " " + currency + ".");
|
||||
} else {
|
||||
int value = viewer.getShop().getBuyPrice(item, player);
|
||||
String name = pointShop ? getPointsName() + "s" : ItemDefinition.forId(viewer.getShop().getCurrency()).getName().toLowerCase();
|
||||
if (value == 1 && (name.charAt(name.length() - 1) == 's')) {
|
||||
name = name.substring(0, name.length() - 1);
|
||||
}
|
||||
player.getPacketDispatch().sendMessage("" + item.getName() + ": currently costs " + value + " " + name + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to send a stock
|
||||
*
|
||||
* @param player
|
||||
* @param tabIndex
|
||||
*/
|
||||
public void sendStock(final Player player, int tabIndex) {
|
||||
final boolean main = tabIndex == 0;
|
||||
player.getPacketDispatch().sendInterfaceConfig(620, 23, !main);
|
||||
player.getPacketDispatch().sendInterfaceConfig(620, 24, main);
|
||||
player.getPacketDispatch().sendInterfaceConfig(620, 29, !main);
|
||||
player.getPacketDispatch().sendInterfaceConfig(620, 25, main);
|
||||
player.getPacketDispatch().sendInterfaceConfig(620, 27, main);
|
||||
player.getPacketDispatch().sendInterfaceConfig(620, 26, false);
|
||||
player.getPacketDispatch().sendAccessMask(1278, main ? 23 : 24, 620, 0, 40);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to update the viewers.
|
||||
*/
|
||||
public void update() {
|
||||
for (ShopViewer viewer : viewers) {
|
||||
viewer.update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to restock the shop.
|
||||
*/
|
||||
public void restock() {
|
||||
for (Container container : containers) {
|
||||
for (int i = 0; i < container.toArray().length; i++) {
|
||||
final boolean main = (container == containers[0]);
|
||||
final Item item = container.toArray()[i];
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
boolean reduce = !main;
|
||||
if (main) {
|
||||
if (item.getAmount() < items[i].getAmount()) {
|
||||
item.setAmount(item.getAmount() + 1);
|
||||
}
|
||||
reduce = item.getAmount() > items[i].getAmount();
|
||||
}
|
||||
if (reduce) {
|
||||
int amount = item.getAmount() - 1;
|
||||
if (amount < 1 && !main) {
|
||||
container.remove(item);
|
||||
} else {
|
||||
item.setAmount(amount);
|
||||
}
|
||||
if (!main) {
|
||||
container.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player can sell an item to the shop.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param item the item.
|
||||
* @param def the def.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean canSell(Player player, Item item, ItemDefinition def) {
|
||||
if (pointShop || item.getDefinition().hasDestroyAction() || !def.isTradeable() || !itemAllowed(item.getId())) {
|
||||
player.getPacketDispatch().sendMessage("You can't sell this item to this shop.");
|
||||
return false;
|
||||
}
|
||||
if (item.getId() == getCurrency()) {
|
||||
player.getPacketDispatch().sendMessage("You can't sell " + item.getName().toLowerCase() + " to a shop.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount to buy/sell.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param add the added item.
|
||||
* @return the amount.
|
||||
*/
|
||||
public int getAmount(Player player, Item add) {
|
||||
return add.getAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player can buy the item.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param currency the currency.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean handleBuy(Player player, Item currency) {
|
||||
return pointShop || player.getInventory().remove(currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player can buy from the shop.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param item the item.
|
||||
* @param price the price.
|
||||
* @param currency the currency.
|
||||
* @return {@code True} if they can buy.
|
||||
*/
|
||||
public boolean canBuy(Player player, Item item, int price, Item currency) {
|
||||
if (!pointShop && !player.getInventory().containsItem(currency)) {
|
||||
player.getPacketDispatch().sendMessage("You don't have enough " + ItemDefinition.forId(getCurrency()).getName().toLowerCase() + ".");
|
||||
return false;
|
||||
}
|
||||
if (pointShop && getPoints(player) < price) {
|
||||
player.sendMessage("You don't have enough " + getPointsName() + "s.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the points.
|
||||
*
|
||||
* @param player the player.
|
||||
* @return the points.
|
||||
*/
|
||||
public int getPoints(Player player) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements the points.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param decrement the decrementation.
|
||||
*/
|
||||
public void decrementPoints(Player player, int decrement) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the points name.
|
||||
*
|
||||
* @return the name.
|
||||
*/
|
||||
public String getPointsName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value gained for selling this item to a certain shop.
|
||||
*
|
||||
* @param item The item to sell.
|
||||
* @param player the player.
|
||||
* @return The value.
|
||||
*/
|
||||
public int getSellingValue(Item item, Player player) {
|
||||
if (!item.getDefinition().isUnnoted()) {
|
||||
player.setAttribute("shop:originalId",item.getId());
|
||||
item = new Item(item.getNoteChange(), item.getAmount());
|
||||
}
|
||||
int amount = getContainer(1).getAmount(item);
|
||||
if (amount < 1) {
|
||||
amount = getContainer(0).getAmount(item);
|
||||
}
|
||||
int value = getSellValue(player, amount, item);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selling value formula based.
|
||||
*
|
||||
* @param amount the amount.
|
||||
* @param item the item.
|
||||
* @return the selling value.
|
||||
*/
|
||||
private int getSellValue(Player player, int amount, Item item) {
|
||||
int id = player.getAttribute("shop:originalId",item.getId());
|
||||
if(item.getAmount() > ContentAPI.amountInInventory(player, id)){
|
||||
item.setAmount(ContentAPI.amountInInventory(player, id));
|
||||
player.removeAttribute("shop:originalId");
|
||||
}
|
||||
double diff = item.getDefinition().isStackable() ? 0.005 : 0.05;
|
||||
double maxMod = 1.0 - (amount * diff);
|
||||
if (maxMod < 0.25) {
|
||||
maxMod = 0.25;
|
||||
}
|
||||
double minMod = maxMod - ((item.getAmount() - 1) * diff);
|
||||
if (minMod < 0.25) {
|
||||
minMod = 0.25;
|
||||
}
|
||||
double mod = (maxMod + minMod) / 2;
|
||||
SystemLogger.logInfo("" + item.getDefinition().getAlchemyValue(highAlch) + " " + mod + " " + item.getAmount());
|
||||
int baseValue = item.getDefinition().getAlchemyValue(highAlch);
|
||||
int value = (int) (baseValue * mod * item.getAmount());
|
||||
if(getCurrency() == Items.TOKKUL_6529 && item.getId() == Items.CHAOS_RUNE_562) value = 13;
|
||||
if(getCurrency() == Items.TOKKUL_6529 && item.getId() == Items.DEATH_RUNE_560) value = 27;
|
||||
if(item.getId() == 12183){
|
||||
value = 25 * item.getAmount();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buying price.
|
||||
*
|
||||
* @param item the item.
|
||||
* @return the price.
|
||||
*/
|
||||
public int getBuyPrice(Item item, Player player) {
|
||||
item = new Item(item.getId(), 1);
|
||||
int price = item.getDefinition().getMaxValue();
|
||||
int sellVal = getSellingValue(item, player);
|
||||
if (price < sellVal) {
|
||||
price = getSellValue(player, 0, item) + sellVal - (sellVal - item.getDefinition().getMaxValue());
|
||||
}
|
||||
if (price < 0) {
|
||||
price = 1;
|
||||
}
|
||||
if (getCurrency() == TOKKUL) {
|
||||
int tokkul = item.getDefinition().getConfiguration("tokkul_price", -1);
|
||||
if (tokkul > 0) {
|
||||
price = tokkul;
|
||||
}
|
||||
if (player.getAchievementDiaryManager().getKaramjaGlove() != -1) {
|
||||
price *= 0.86666666667;
|
||||
}
|
||||
}
|
||||
if (getCurrency() == ARCHERY_TICKET) {
|
||||
int tickets = item.getDefinition().getConfiguration(ItemConfigParser.ARCHERY_TICKET_PRICE,-1);
|
||||
if (tickets > 0) {
|
||||
price = tickets;
|
||||
}
|
||||
}
|
||||
return (getSellAllFor() > 0 ? getSellAllFor() : price);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the item is allowed to be sold to the shop.
|
||||
*
|
||||
* @param itemId the item id.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean itemAllowed(int itemId) {
|
||||
if (general) {
|
||||
return true;
|
||||
}
|
||||
int noteId = ItemDefinition.forId(itemId).getNoteId();
|
||||
if (!ItemDefinition.forId(itemId).isUnnoted()) {
|
||||
noteId = ItemDefinition.forId(noteId).getNoteId();
|
||||
}
|
||||
for (Item id : items) {
|
||||
if (itemId == id.getId() || (noteId > -1 && noteId == ItemDefinition.forId(id.getId()).getNoteId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the container the item should go to.
|
||||
*
|
||||
* @param item the item.
|
||||
* @return the container.
|
||||
*/
|
||||
public Container getContainer(Item item) {
|
||||
int itemId = item.getId();
|
||||
int noteId = ItemDefinition.forId(itemId).getNoteId();
|
||||
if (!ItemDefinition.forId(itemId).isUnnoted()) {
|
||||
noteId = ItemDefinition.forId(noteId).getNoteId();
|
||||
}
|
||||
for (Item i : items) {
|
||||
if (i.getId() == item.getId() || (noteId > -1 && noteId == ItemDefinition.forId(i.getId()).getNoteId())) {
|
||||
return getContainer(0);
|
||||
}
|
||||
}
|
||||
return getContainer(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this shop.
|
||||
*
|
||||
* @return the shop.
|
||||
*/
|
||||
public Shop copy() {
|
||||
return new Shop(title, items, general, currency, highAlch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the container on the slot.
|
||||
*
|
||||
* @param tabIndex the tab index.
|
||||
* @return the container.
|
||||
*/
|
||||
public Container getContainer(int tabIndex) {
|
||||
if (tabIndex > containers.length) {
|
||||
throw new IndexOutOfBoundsException("Error! Shop tab index out of bounds.");
|
||||
}
|
||||
return containers[tabIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the viewers.
|
||||
*
|
||||
* @return The viewers.
|
||||
*/
|
||||
public List<ShopViewer> getViewers() {
|
||||
return viewers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the title.
|
||||
*
|
||||
* @return The title.
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items.
|
||||
*
|
||||
* @return The items.
|
||||
*/
|
||||
public Item[] getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the items.
|
||||
*
|
||||
* @return true if the items were changed.
|
||||
*/
|
||||
public boolean setItems(Item... item) {
|
||||
return items == item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the general.
|
||||
*
|
||||
* @return The general.
|
||||
*/
|
||||
public boolean isGeneral() {
|
||||
return general;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currency.
|
||||
*
|
||||
* @return The currency.
|
||||
*/
|
||||
public int getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the containers.
|
||||
*
|
||||
* @return The containers.
|
||||
*/
|
||||
public Container[] getContainers() {
|
||||
return containers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bhighAlch.
|
||||
*
|
||||
* @return the highAlch
|
||||
*/
|
||||
public boolean isHighAlch() {
|
||||
return highAlch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Shop [containers=" + Arrays.toString(containers) + ", viewers=" + viewers + ", title=" + title + ", items=" + Arrays.toString(items) + ", general=" + general + ", currency=" + currency + ", highAlch=" + highAlch + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lastRestock.
|
||||
*
|
||||
* @return the lastRestock
|
||||
*/
|
||||
public int getLastRestock() {
|
||||
return lastRestock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the balastRestock.
|
||||
*
|
||||
* @param lastRestock the lastRestock to set.
|
||||
*/
|
||||
public void setLastRestock(int lastRestock) {
|
||||
this.lastRestock = lastRestock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the npcs.
|
||||
*
|
||||
* @return the npcs
|
||||
*/
|
||||
public int[] getNpcs() {
|
||||
return npcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the banpcs.
|
||||
*
|
||||
* @param npcs the npcs to set.
|
||||
*/
|
||||
public void setNpcs(int[] npcs) {
|
||||
this.npcs = npcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pointShop.
|
||||
*
|
||||
* @return the pointShop
|
||||
*/
|
||||
public boolean isPointShop() {
|
||||
return pointShop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pointShop.
|
||||
*
|
||||
* @param pointShop the pointShop to set.
|
||||
*/
|
||||
public void setPointShop(boolean pointShop) {
|
||||
this.pointShop = pointShop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if shop should restock.
|
||||
*
|
||||
* @return the restock
|
||||
*/
|
||||
public boolean isRestock() {
|
||||
return restock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the restock.
|
||||
*
|
||||
* @param reStock
|
||||
*/
|
||||
public void setRestock(boolean reStock) {
|
||||
restock = reStock;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the SellAllFor value.
|
||||
*
|
||||
* @return the sellAllFor
|
||||
*/
|
||||
public int getSellAllFor() {
|
||||
return sellAllFor;
|
||||
}
|
||||
|
||||
public void setItems(ArrayList<Item> items){
|
||||
this.items = items.toArray(new Item[0]);
|
||||
}
|
||||
|
||||
}
|
||||
865
Server/src/main/java/core/game/content/global/shop/Shop.kt
Normal file
865
Server/src/main/java/core/game/content/global/shop/Shop.kt
Normal file
|
|
@ -0,0 +1,865 @@
|
|||
package core.game.content.global.shop
|
||||
|
||||
import rs09.game.world.GameWorld.ticks
|
||||
import api.ContentAPI.amountInInventory
|
||||
import rs09.game.system.SystemLogger.logInfo
|
||||
import core.game.node.entity.player.link.diary.DiaryType
|
||||
import core.cache.def.impl.ItemDefinition
|
||||
import core.game.container.Container
|
||||
import core.game.container.ContainerType
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items.BLACK_CHAINBODY_1107
|
||||
import org.rs09.consts.Items.BOWL_1923
|
||||
import org.rs09.consts.Items.BUCKET_1925
|
||||
import org.rs09.consts.Items.CAKE_TIN_1887
|
||||
import org.rs09.consts.Items.CANDLE_36
|
||||
import org.rs09.consts.Items.CHAOS_RUNE_562
|
||||
import org.rs09.consts.Items.CHISEL_1755
|
||||
import org.rs09.consts.Items.DEATH_RUNE_560
|
||||
import org.rs09.consts.Items.EMPTY_POT_1931
|
||||
import org.rs09.consts.Items.HAMMER_2347
|
||||
import org.rs09.consts.Items.JUG_1935
|
||||
import org.rs09.consts.Items.NEWCOMER_MAP_550
|
||||
import org.rs09.consts.Items.SECURITY_BOOK_9003
|
||||
import org.rs09.consts.Items.SHEARS_1735
|
||||
import org.rs09.consts.Items.TINDERBOX_590
|
||||
import org.rs09.consts.Items.TOKKUL_6529
|
||||
import rs09.game.system.config.ItemConfigParser
|
||||
import java.lang.IndexOutOfBoundsException
|
||||
import java.util.Arrays
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* A class representing a shop.
|
||||
*
|
||||
* @author 'Vexia
|
||||
* @author Jamix77
|
||||
*/
|
||||
open class Shop @JvmOverloads constructor(
|
||||
/**
|
||||
* Represents the title of the shop.
|
||||
*/
|
||||
val title: String,
|
||||
/**
|
||||
* Represents the items in the store.
|
||||
*/
|
||||
var items: Array<Item>,
|
||||
/**
|
||||
* Represents if it's a general store.
|
||||
*/
|
||||
val isGeneral: Boolean,
|
||||
/**
|
||||
* Represents the currency the shop allows.
|
||||
*/
|
||||
val currency: Int = COINS,
|
||||
/**
|
||||
* If the shop buys for high alch.
|
||||
*/
|
||||
val isHighAlch: Boolean = false
|
||||
) {
|
||||
/**
|
||||
* Gets the containers.
|
||||
*
|
||||
* @return The containers.
|
||||
*/
|
||||
/**
|
||||
* Represents the shop containers.
|
||||
*/
|
||||
val containers = arrayOf(Container(40, ContainerType.SHOP), Container(40, ContainerType.SHOP))
|
||||
/**
|
||||
* Gets the viewers.
|
||||
*
|
||||
* @return The viewers.
|
||||
*/
|
||||
/**
|
||||
* Represents the list of shop viewers.
|
||||
*/
|
||||
val viewers: List<ShopViewer> = ArrayList(20)
|
||||
/**
|
||||
* Gets the title.
|
||||
*
|
||||
* @return The title.
|
||||
*/
|
||||
/**
|
||||
* Gets the items.
|
||||
*
|
||||
* @return The items.
|
||||
*/
|
||||
/**
|
||||
* Gets the general.
|
||||
*
|
||||
* @return The general.
|
||||
*/
|
||||
/**
|
||||
* Gets the currency.
|
||||
*
|
||||
* @return The currency.
|
||||
*/
|
||||
/**
|
||||
* Gets the bhighAlch.
|
||||
*
|
||||
* @return the highAlch
|
||||
*/
|
||||
/**
|
||||
* Gets the SellAllFor value.
|
||||
*
|
||||
* @return the sellAllFor
|
||||
*/
|
||||
/**
|
||||
* Sell price for all shop items, if needed.
|
||||
*/
|
||||
var sellAllFor = 0
|
||||
private set
|
||||
/**
|
||||
* Gets the lastRestock.
|
||||
*
|
||||
* @return the lastRestock
|
||||
*/
|
||||
/**
|
||||
* Sets the balastRestock.
|
||||
*
|
||||
* @param lastRestock the lastRestock to set.
|
||||
*/
|
||||
/**
|
||||
* The last restock.
|
||||
*/
|
||||
var lastRestock = 0
|
||||
/**
|
||||
* Check if shop should restock.
|
||||
*
|
||||
* @return the restock
|
||||
*/
|
||||
/**
|
||||
* Sets the restock.
|
||||
*
|
||||
* @param reStock
|
||||
*/
|
||||
/**
|
||||
* If the shop should restock.
|
||||
*/
|
||||
var isRestock = false
|
||||
/**
|
||||
* Gets the pointShop.
|
||||
*
|
||||
* @return the pointShop
|
||||
*/
|
||||
/**
|
||||
* Sets the pointShop.
|
||||
*
|
||||
* @param pointShop the pointShop to set.
|
||||
*/
|
||||
/**
|
||||
* If it's a point shop.
|
||||
*/
|
||||
var isPointShop = false
|
||||
/**
|
||||
* Gets the npcs.
|
||||
*
|
||||
* @return the npcs
|
||||
*/
|
||||
/**
|
||||
* Sets the banpcs.
|
||||
*
|
||||
* @param npcs the npcs to set.
|
||||
*/
|
||||
/**
|
||||
* The npcs of the shop.
|
||||
*/
|
||||
var npcs: IntArray = intArrayOf()
|
||||
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param items the items.
|
||||
* @param general the general.
|
||||
* @param currency the currency.
|
||||
* @param highAlch if high alch.
|
||||
* @param restock if restock.
|
||||
*/
|
||||
constructor(
|
||||
title: String,
|
||||
items: Array<Item>,
|
||||
general: Boolean,
|
||||
currency: Int,
|
||||
highAlch: Boolean,
|
||||
restock: Boolean,
|
||||
sellAllFor: Int
|
||||
) : this(title, items, general, currency, highAlch) {
|
||||
this.sellAllFor = sellAllFor
|
||||
isRestock = restock
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`
|
||||
*
|
||||
* @param title the shop title
|
||||
* @param items items the shop can handle
|
||||
* @param general is this a general store
|
||||
* @param currency what currency is used
|
||||
*/
|
||||
constructor(title: String, items: Array<Item>, npcs: IntArray, general: Boolean, currency: Int) : this(
|
||||
title,
|
||||
items,
|
||||
general,
|
||||
currency,
|
||||
false
|
||||
) {
|
||||
this.npcs = npcs
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param general the general.
|
||||
*/
|
||||
constructor(title: String, general: Boolean) : this(title, GENERAL_STORE_ITEMS, general) {}
|
||||
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param general the general.
|
||||
* @param highAlch if highAlch.
|
||||
*/
|
||||
constructor(title: String, general: Boolean, highAlch: Boolean) : this(
|
||||
title,
|
||||
GENERAL_STORE_ITEMS,
|
||||
general,
|
||||
COINS,
|
||||
highAlch
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param general the general.
|
||||
* @param highAlch if highAlch.
|
||||
*/
|
||||
constructor(title: String, general: Boolean, currency: Int, highAlch: Boolean) : this(
|
||||
title,
|
||||
GENERAL_STORE_ITEMS,
|
||||
general,
|
||||
currency,
|
||||
highAlch
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param items the items.
|
||||
* @param npcs the npcs.
|
||||
* @param general the general.
|
||||
*/
|
||||
constructor(title: String, items: Array<Item>, npcs: IntArray, general: Boolean) : this(
|
||||
title,
|
||||
items,
|
||||
general,
|
||||
COINS,
|
||||
false
|
||||
) {
|
||||
this.npcs = npcs
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param npcs the npcs.
|
||||
* @param general the general.
|
||||
*/
|
||||
constructor(title: String, npcs: IntArray, general: Boolean) : this(title, GENERAL_STORE_ITEMS, npcs, general) {
|
||||
this.npcs = npcs
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param npcs the npcs.
|
||||
* @param general the general.
|
||||
* @param highAlch if highAlch.
|
||||
*/
|
||||
constructor(title: String, npcs: IntArray, general: Boolean, highAlch: Boolean) : this(
|
||||
title,
|
||||
GENERAL_STORE_ITEMS,
|
||||
general,
|
||||
995,
|
||||
highAlch
|
||||
) {
|
||||
this.npcs = npcs
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to open the shop.
|
||||
*
|
||||
* @param player the shop.
|
||||
*/
|
||||
fun open(player: Player) {
|
||||
ShopViewer.extend(player, this).open()
|
||||
|
||||
// Browse the Lumbridge General Store
|
||||
if (title.equals("Lumbridge General Store", ignoreCase = true)) {
|
||||
player.achievementDiaryManager.finishTask(player, DiaryType.LUMBRIDGE, 0, 18)
|
||||
}
|
||||
|
||||
// Browse through Oziach's Armour Shop
|
||||
if (title.equals("Oziach's Armour", ignoreCase = true)) {
|
||||
player.achievementDiaryManager.finishTask(player, DiaryType.VARROCK, 1, 20)
|
||||
}
|
||||
}
|
||||
|
||||
fun give(player: Player, slot: Int, amount: Int, tabIndex: Int) {
|
||||
val container = getContainer(tabIndex)
|
||||
val item = container[slot] ?: return
|
||||
val add = Item(item.id, amount)
|
||||
if (add.amount < 1 || !player.inventory.hasSpaceFor(add)) {
|
||||
player.packetDispatch.sendMessage("You have no inventory space at the moment and cannot get anything.")
|
||||
return
|
||||
}
|
||||
add.amount = getAmount(player, add)
|
||||
if (add.amount < 1 || !player.inventory.hasSpaceFor(add)) {
|
||||
player.packetDispatch.sendMessage("You have no inventory space at the moment and cannot get anything.")
|
||||
return
|
||||
}
|
||||
player.inventory.add(add)
|
||||
update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to buy an item from the shop.
|
||||
*
|
||||
* @param slot the slot.
|
||||
* @param amount the amount.
|
||||
*/
|
||||
fun buy(player: Player, slot: Int, amount: Int, tabIndex: Int) {
|
||||
var amount = amount
|
||||
if (tabIndex == 1 && player.ironmanManager.checkRestriction()) {
|
||||
return
|
||||
}
|
||||
val container = getContainer(tabIndex)
|
||||
val item = container[slot] ?: return
|
||||
if (item.amount == 0) {
|
||||
player.packetDispatch.sendMessage("There is no stock of that item at the moment.")
|
||||
return
|
||||
}
|
||||
if (amount > item.amount && item.amount != -1) {
|
||||
amount = item.amount
|
||||
}
|
||||
val add = Item(item.id, amount)
|
||||
if (player.inventory.getMaximumAdd(add) < amount) {
|
||||
add.amount = player.inventory.getMaximumAdd(add)
|
||||
}
|
||||
if (add.amount < 1 || !player.inventory.hasSpaceFor(add)) {
|
||||
player.packetDispatch.sendMessage("You have no inventory space at the moment and cannot buy anything.")
|
||||
return
|
||||
}
|
||||
add.amount = getAmount(player, add)
|
||||
if (add.amount < 1 || !player.inventory.hasSpaceFor(add)) {
|
||||
player.packetDispatch.sendMessage("You have no inventory space at the moment and cannot buy anything.")
|
||||
return
|
||||
}
|
||||
val price = add.amount * getBuyPrice(item, player)
|
||||
val currency = Item(currency, price)
|
||||
if (!canBuy(player, item, price, currency)) {
|
||||
return
|
||||
}
|
||||
if (handleBuy(player, currency)) {
|
||||
if (isPointShop) {
|
||||
decrementPoints(player, price)
|
||||
}
|
||||
if (tabIndex == 0) {
|
||||
if (container.getAmount(item) != -1) container.replace(
|
||||
Item(
|
||||
item.id,
|
||||
container.getAmount(item) - add.amount
|
||||
), slot, true
|
||||
)
|
||||
} else {
|
||||
container.remove(add)
|
||||
container.shift()
|
||||
}
|
||||
|
||||
// Achievement Diary Handlers
|
||||
if (add.id == BLACK_CHAINBODY_1107 && title.equals("Wayne's Chains", ignoreCase = true) && !player.getAttribute("diary:falador:black-chain-bought", false)) {
|
||||
player.setAttribute("/save:diary:falador:black-chain-bought", true)
|
||||
}
|
||||
if (add.id == 12622 && title.equals("Sarah's Farming Shop", ignoreCase = true)) {
|
||||
player.achievementDiaryManager.finishTask(player, DiaryType.FALADOR, 0, 0)
|
||||
}
|
||||
if (add.id == CANDLE_36 && title.equals("Candle Shop", ignoreCase = true)) {
|
||||
player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 0, 9)
|
||||
}
|
||||
if (title.equals("Ranging Guild Ticket Exchange", ignoreCase = true)) {
|
||||
player.achievementDiaryManager.finishTask(player, DiaryType.SEERS_VILLAGE, 1, 8)
|
||||
}
|
||||
player.inventory.add(add)
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to sell an item to the shop.
|
||||
*
|
||||
* @param slot the slot.
|
||||
* @param amount the amount.
|
||||
*/
|
||||
fun sell(player: Player, slot: Int, amount: Int, tabIndex: Int) {
|
||||
var amount = amount
|
||||
var tabIndex = tabIndex
|
||||
val item = player.inventory[slot] ?: return
|
||||
val def = ItemDefinition.forId(item.id)
|
||||
if (!canSell(player, item, def)) {
|
||||
return
|
||||
}
|
||||
val container = getContainer(item)
|
||||
if (amount > player.inventory.getAmount(item)) {
|
||||
amount = player.inventory.getAmount(item)
|
||||
}
|
||||
var add = Item(item.id, amount)
|
||||
if (add.amount > container.getMaximumAdd(add)) {
|
||||
add.amount = container.getMaximumAdd(add)
|
||||
}
|
||||
player.debug("" + add.amount)
|
||||
if (!container.hasSpaceFor(add) || add.amount < 1) {
|
||||
player.packetDispatch.sendMessage("The shop has ran out of space.")
|
||||
return
|
||||
}
|
||||
val currency = Item(currency, getSellingValue(add, player))
|
||||
if (item.definition.isStackable) {
|
||||
if (!player.inventory.hasSpaceFor(currency)) {
|
||||
player.packetDispatch.sendMessage("You don't have enough space for that many " + currency.name.toLowerCase() + ".")
|
||||
return
|
||||
}
|
||||
}
|
||||
player.debug("Selling item")
|
||||
if (player.inventory.remove(add, slot, true)) {
|
||||
if (currency.amount > player.inventory.getMaximumAdd(currency)) {
|
||||
currency.amount = player.inventory.getMaximumAdd(currency)
|
||||
}
|
||||
if (!add.definition.isUnnoted) {
|
||||
add = Item(add.noteChange, add.amount)
|
||||
}
|
||||
if (container.getAmount(add.id) == -1 || container.add(add)) {
|
||||
if (currency.amount > 0) {
|
||||
player.debug("Adding coins to inventory")
|
||||
player.inventory.add(currency)
|
||||
}
|
||||
val viewer = player.getExtension<ShopViewer>(ShopViewer::class.java)
|
||||
tabIndex = if (container === containers[0]) 0 else 1
|
||||
sendStock(player, tabIndex)
|
||||
if (viewer != null) {
|
||||
viewer.tabIndex = tabIndex
|
||||
}
|
||||
update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Values an item.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param viewer the viewer.
|
||||
* @param item the item.
|
||||
* @param sell the sell.
|
||||
*/
|
||||
fun value(player: Player, viewer: ShopViewer, item: Item, sell: Boolean) {
|
||||
if (sell) {
|
||||
if (isPointShop || item.id == viewer.shop.currency || !item.definition.isTradeable || !viewer.shop.itemAllowed(
|
||||
item.id
|
||||
)
|
||||
) {
|
||||
player.packetDispatch.sendMessage("You can't sell this item.")
|
||||
return
|
||||
}
|
||||
val value = viewer.shop.getSellingValue(Item(item.id, 1), player)
|
||||
var currency =
|
||||
if (isPointShop) pointsName else ItemDefinition.forId(viewer.shop.currency).name.toLowerCase()
|
||||
if (value == 1 && currency[currency.length - 1] == 's') {
|
||||
currency = currency.substring(0, currency.length - 1)
|
||||
}
|
||||
player.packetDispatch.sendMessage(item.name + ": shop will buy for " + value + " " + currency + ".")
|
||||
} else {
|
||||
val value = viewer.shop.getBuyPrice(item, player)
|
||||
var name =
|
||||
if (isPointShop) pointsName + "s" else ItemDefinition.forId(viewer.shop.currency).name.toLowerCase()
|
||||
if (value == 1 && name[name.length - 1] == 's') {
|
||||
name = name.substring(0, name.length - 1)
|
||||
}
|
||||
player.packetDispatch.sendMessage("" + item.name + ": currently costs " + value + " " + name + ".")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to send a stock
|
||||
*
|
||||
* @param player
|
||||
* @param tabIndex
|
||||
*/
|
||||
fun sendStock(player: Player, tabIndex: Int) {
|
||||
val main = tabIndex == 0
|
||||
player.packetDispatch.sendInterfaceConfig(620, 23, !main)
|
||||
player.packetDispatch.sendInterfaceConfig(620, 24, main)
|
||||
player.packetDispatch.sendInterfaceConfig(620, 29, !main)
|
||||
player.packetDispatch.sendInterfaceConfig(620, 25, main)
|
||||
player.packetDispatch.sendInterfaceConfig(620, 27, main)
|
||||
player.packetDispatch.sendInterfaceConfig(620, 26, false)
|
||||
player.packetDispatch.sendAccessMask(1278, if (main) 23 else 24, 620, 0, 40)
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to update the viewers.
|
||||
*/
|
||||
fun update() {
|
||||
for (viewer in viewers) {
|
||||
viewer.update()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to restock the shop.
|
||||
*/
|
||||
fun restock() {
|
||||
for (container in containers) {
|
||||
for (i in container.toArray().indices) {
|
||||
val main = container === containers[0]
|
||||
val item = container.toArray()[i] ?: continue
|
||||
var reduce = !main
|
||||
if (main) {
|
||||
if (item.amount < items[i].amount) {
|
||||
item.amount = item.amount + 1
|
||||
}
|
||||
reduce = item.amount > items[i].amount
|
||||
}
|
||||
if (reduce) {
|
||||
val amount = item.amount - 1
|
||||
if (amount < 1 && !main) {
|
||||
container.remove(item)
|
||||
} else {
|
||||
item.amount = amount
|
||||
}
|
||||
if (!main) {
|
||||
container.shift()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player can sell an item to the shop.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param item the item.
|
||||
* @param def the def.
|
||||
* @return `True` if so.
|
||||
*/
|
||||
open fun canSell(player: Player, item: Item, def: ItemDefinition): Boolean {
|
||||
if (isPointShop || item.definition.hasDestroyAction() || !def.isTradeable || !itemAllowed(item.id)) {
|
||||
player.packetDispatch.sendMessage("You can't sell this item to this shop.")
|
||||
return false
|
||||
}
|
||||
if (item.id == currency) {
|
||||
player.packetDispatch.sendMessage("You can't sell " + item.name.toLowerCase() + " to a shop.")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount to buy/sell.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param add the added item.
|
||||
* @return the amount.
|
||||
*/
|
||||
fun getAmount(player: Player?, add: Item): Int {
|
||||
return add.amount
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player can buy the item.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param currency the currency.
|
||||
* @return `True` if so.
|
||||
*/
|
||||
fun handleBuy(player: Player, currency: Item?): Boolean {
|
||||
return isPointShop || player.inventory.remove(currency)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player can buy from the shop.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param item the item.
|
||||
* @param price the price.
|
||||
* @param currency the currency.
|
||||
* @return `True` if they can buy.
|
||||
*/
|
||||
fun canBuy(player: Player, item: Item, price: Int, currency: Item): Boolean {
|
||||
if (!isPointShop && !player.inventory.containsItem(currency)) {
|
||||
player.packetDispatch.sendMessage(
|
||||
"You don't have enough " + ItemDefinition.forId(currency.id).name.toLowerCase() + "."
|
||||
)
|
||||
return false
|
||||
}
|
||||
if (isPointShop && getPoints(player) < price) {
|
||||
player.sendMessage("You don't have enough " + pointsName + "s.")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the points.
|
||||
*
|
||||
* @param player the player.
|
||||
* @return the points.
|
||||
*/
|
||||
fun getPoints(player: Player?): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements the points.
|
||||
*
|
||||
* @param player the player.
|
||||
* @param decrement the decrementation.
|
||||
*/
|
||||
fun decrementPoints(player: Player?, decrement: Int) {}
|
||||
|
||||
/**
|
||||
* Gets the points name.
|
||||
*
|
||||
* @return the name.
|
||||
*/
|
||||
val pointsName: String
|
||||
get() = ""
|
||||
|
||||
/**
|
||||
* Gets the value gained for selling this item to a certain shop.
|
||||
*
|
||||
* @param item The item to sell.
|
||||
* @param player the player.
|
||||
* @return The value.
|
||||
*/
|
||||
fun getSellingValue(item: Item, player: Player): Int {
|
||||
var item = item
|
||||
if (!item.definition.isUnnoted) {
|
||||
player.setAttribute("shop:originalId", item.id)
|
||||
item = Item(item.noteChange, item.amount)
|
||||
}
|
||||
var amount = getContainer(1).getAmount(item)
|
||||
if (amount < 1) {
|
||||
amount = getContainer(0).getAmount(item)
|
||||
}
|
||||
return getSellingValue(player, amount, item)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selling value formula based.
|
||||
*
|
||||
* @param amount the amount.
|
||||
* @param item the item.
|
||||
* @return the selling value.
|
||||
*/
|
||||
private fun getSellingValue(player: Player, amount: Int, item: Item): Int {
|
||||
val id = player.getAttribute("shop:originalId", item.id)
|
||||
if (item.amount > amountInInventory(player, id)) {
|
||||
item.amount = amountInInventory(player, id)
|
||||
player.removeAttribute("shop:originalId")
|
||||
}
|
||||
val diff = if (item.definition.isStackable) 0.005 else 0.05
|
||||
var maxMod = 1.0 - amount * diff
|
||||
if (maxMod < 0.25) {
|
||||
maxMod = 0.25
|
||||
}
|
||||
var minMod = maxMod - (item.amount - 1) * diff
|
||||
if (minMod < 0.25) {
|
||||
minMod = 0.25
|
||||
}
|
||||
val mod = (maxMod + minMod) / 2
|
||||
logInfo("" + item.definition.getAlchemyValue(isHighAlch) + " " + mod + " " + item.amount)
|
||||
val baseValue = item.definition.getAlchemyValue(isHighAlch)
|
||||
var value = (baseValue * mod * item.amount).toInt()
|
||||
if (currency == TOKKUL_6529 && item.id == CHAOS_RUNE_562) value = 13 * item.amount
|
||||
if (currency == TOKKUL_6529 && item.id == DEATH_RUNE_560) value = 27 * item.amount
|
||||
if (item.id == 12183) {
|
||||
value = 25 * item.amount
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buying price.
|
||||
*
|
||||
* @param item the item.
|
||||
* @return the price.
|
||||
*/
|
||||
open fun getBuyPrice(item: Item, player: Player): Int {
|
||||
var item = item
|
||||
item = Item(item.id, 1)
|
||||
var price = item.definition.maxValue
|
||||
val sellVal = getSellingValue(item, player)
|
||||
if (price < sellVal) {
|
||||
price = getSellingValue(player, 0, item) + sellVal - (sellVal - item.definition.maxValue)
|
||||
}
|
||||
if (price < 0) {
|
||||
price = 1
|
||||
}
|
||||
if (currency == TOKKUL) {
|
||||
val tokkul = item.definition.getConfiguration("tokkul_price", -1)
|
||||
if (tokkul > 0) {
|
||||
price = tokkul
|
||||
}
|
||||
if (player.achievementDiaryManager.karamjaGlove != -1) {
|
||||
price = kotlin.math.floor(price * 0.87).toInt()
|
||||
}
|
||||
}
|
||||
if (currency == ARCHERY_TICKET) {
|
||||
val tickets = item.definition.getConfiguration(ItemConfigParser.ARCHERY_TICKET_PRICE, -1)
|
||||
if (tickets > 0) {
|
||||
price = tickets
|
||||
}
|
||||
}
|
||||
return if (sellAllFor > 0) sellAllFor else price
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the item is allowed to be sold to the shop.
|
||||
*
|
||||
* @param itemId the item id.
|
||||
* @return `True` if so.
|
||||
*/
|
||||
fun itemAllowed(itemId: Int): Boolean {
|
||||
if (isGeneral) {
|
||||
return true
|
||||
}
|
||||
var noteId = ItemDefinition.forId(itemId).noteId
|
||||
if (!ItemDefinition.forId(itemId).isUnnoted) {
|
||||
noteId = ItemDefinition.forId(noteId).noteId
|
||||
}
|
||||
for (id in items) {
|
||||
if (itemId == id.id || noteId > -1 && noteId == ItemDefinition.forId(id.id).noteId) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the container the item should go to.
|
||||
*
|
||||
* @param item the item.
|
||||
* @return the container.
|
||||
*/
|
||||
fun getContainer(item: Item): Container {
|
||||
val itemId = item.id
|
||||
var noteId = ItemDefinition.forId(itemId).noteId
|
||||
if (!ItemDefinition.forId(itemId).isUnnoted) {
|
||||
noteId = ItemDefinition.forId(noteId).noteId
|
||||
}
|
||||
for (i in items) {
|
||||
if (i.id == item.id || noteId > -1 && noteId == ItemDefinition.forId(i.id).noteId) {
|
||||
return getContainer(0)
|
||||
}
|
||||
}
|
||||
return getContainer(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this shop.
|
||||
*
|
||||
* @return the shop.
|
||||
*/
|
||||
fun copy(): Shop {
|
||||
return Shop(title, items, isGeneral, currency, isHighAlch)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the container on the slot.
|
||||
*
|
||||
* @param tabIndex the tab index.
|
||||
* @return the container.
|
||||
*/
|
||||
fun getContainer(tabIndex: Int): Container {
|
||||
if (tabIndex > containers.size) {
|
||||
throw IndexOutOfBoundsException("Error! Shop tab index out of bounds.")
|
||||
}
|
||||
return containers[tabIndex]
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Shop [containers=" + Arrays.toString(containers) + ", viewers=" + viewers + ", title=" + title + ", items=" + Arrays.toString(
|
||||
items
|
||||
) + ", general=" + isGeneral + ", currency=" + currency + ", highAlch=" + isHighAlch + "]"
|
||||
}
|
||||
|
||||
fun setItems(items: ArrayList<Item>) {
|
||||
this.items = items.toTypedArray()
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Represents the general store items.
|
||||
*/
|
||||
val GENERAL_STORE_ITEMS = arrayOf(
|
||||
Item(EMPTY_POT_1931, 5),
|
||||
Item(JUG_1935, 5),
|
||||
Item(SHEARS_1735, 2),
|
||||
Item(BUCKET_1925, 3),
|
||||
Item(BOWL_1923, 2),
|
||||
Item(CAKE_TIN_1887, 2),
|
||||
Item(TINDERBOX_590, 2),
|
||||
Item(CHISEL_1755, 2),
|
||||
Item(HAMMER_2347, 5),
|
||||
Item(NEWCOMER_MAP_550, 5),
|
||||
Item(SECURITY_BOOK_9003, 5)
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents the coins item.
|
||||
*/
|
||||
private const val COINS = 995
|
||||
|
||||
/**
|
||||
* Represents the tokkul item id.
|
||||
*/
|
||||
private const val TOKKUL = 6529
|
||||
|
||||
/**
|
||||
* Represents the archery ticket item id
|
||||
*/
|
||||
private const val ARCHERY_TICKET = 1464
|
||||
}
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param items the items.
|
||||
* @param isGeneral the general.
|
||||
* @param currency the currency.
|
||||
* @param isHighAlch if high alch.
|
||||
*/
|
||||
/**
|
||||
* Constructs a new `Shop` `Object`.
|
||||
*
|
||||
* @param title the title.
|
||||
* @param items the items.
|
||||
* @param general the general.
|
||||
*/
|
||||
init {
|
||||
this.getContainer(0).add(*items)
|
||||
isRestock = true
|
||||
lastRestock = ticks + 100
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,8 @@ import core.game.node.entity.Entity;
|
|||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.object.Scenery;
|
||||
import org.json.simple.JSONObject;
|
||||
import rs09.ServerStore;
|
||||
import rs09.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.zone.MapZone;
|
||||
|
|
@ -261,13 +263,13 @@ public final class ChaosTunnelZone extends MapZone implements Plugin<Object> {
|
|||
* @param player The player.
|
||||
*/
|
||||
private void commenceBorkBattle(Player player) {
|
||||
if ((System.currentTimeMillis() - player.getSavedData().getActivityData().getLastBorkBattle()) < 24 * 60 * 60_000 && GameWorld.getSettings().isHosted()) {
|
||||
if (ServerStore.getBoolean(getStoreFile(), player.getUsername().toLowerCase()) && GameWorld.getSettings().isHosted()) {
|
||||
player.getPacketDispatch().sendMessage("The portal's magic is too weak to teleport you right now.");
|
||||
return;
|
||||
}
|
||||
player.lock(10);
|
||||
player.graphics(Graphics.create(110));
|
||||
player.getSavedData().getActivityData().setLastBorkBattle(System.currentTimeMillis());
|
||||
getStoreFile().put(player.getUsername().toLowerCase(), true);
|
||||
ActivityManager.start(player, "Bork cutscene", false);
|
||||
}
|
||||
|
||||
|
|
@ -352,4 +354,12 @@ public final class ChaosTunnelZone extends MapZone implements Plugin<Object> {
|
|||
PORTALS.put(location, loc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Server Store file for Bork being killed for the day
|
||||
* @return The JSONObject containing the boolean of whether Bork has been killed
|
||||
*/
|
||||
private JSONObject getStoreFile() {
|
||||
return ServerStore.getArchive("daily-bork-killed");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class RoavarDialogue extends DialoguePlugin {
|
|||
stage = 1;
|
||||
break;
|
||||
case 1:
|
||||
interpreter.sendOptions("Select an Option", "Can I buy a beer?", "Can I hear some gossipp?", "Do you have a spare silver sickle?", "Nothing thanks.");
|
||||
interpreter.sendOptions("Select an Option", "Can I buy a beer?", "Can I hear some gossipp?", "Nothing thanks.");
|
||||
stage = 2;
|
||||
break;
|
||||
case 2:
|
||||
|
|
@ -58,10 +58,6 @@ public class RoavarDialogue extends DialoguePlugin {
|
|||
stage = 20;
|
||||
break;
|
||||
case 3:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Would you happen to have a spare silver sickle?");
|
||||
stage = 30;
|
||||
break;
|
||||
case 4:
|
||||
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Nothing thanks.");
|
||||
stage = 40;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package core.game.node.entity.combat.spell;
|
||||
|
||||
import api.ContentAPI;
|
||||
import core.game.node.entity.skill.Skills;
|
||||
import core.game.node.entity.skill.magic.Runes;
|
||||
import core.game.node.entity.Entity;
|
||||
|
|
@ -181,6 +182,11 @@ public final class CurseSpells extends CombatSpell {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addExperience(Entity entity, int hit) {
|
||||
entity.getSkills().addExperience(Skills.MAGIC, getExperience());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plugin<SpellType> newInstance(SpellType type) throws Throwable {
|
||||
SpellBook.MODERN.register(2, new CurseSpells(SpellType.CONFUSE, 3, 13.0, 99, CONFUSE_START, CONFUSE_PROJECTILE, CONFUSE_END, Runes.BODY_RUNE.getItem(1), Runes.EARTH_RUNE.getItem(2), Runes.WATER_RUNE.getItem(3)));
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ public class NPC extends Entity {
|
|||
if (getZoneMonitor().handleDeath(killer)) {
|
||||
return;
|
||||
}
|
||||
if (task != null && killer instanceof Player && ((Player) killer).getSlayer().getTask() == task) {
|
||||
if (task != null && killer instanceof Player && ((Player) killer).getSlayer().getTask() == task && ((Player) killer).getSlayer().hasTask()) {
|
||||
((Player) killer).getSlayer().finalizeDeath(killer.asPlayer(), this);
|
||||
}
|
||||
if (killer instanceof Player && killer.getAttribute("jobs:id",null) != null) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ import org.rs09.consts.Items;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static java.lang.Math.floor;
|
||||
import static java.lang.Math.max;
|
||||
|
||||
/**
|
||||
* Represents an entity's skills.
|
||||
* @author Emperor
|
||||
|
|
@ -453,8 +456,8 @@ public final class Skills {
|
|||
int points = 0;
|
||||
int output = 0;
|
||||
for (byte lvl = 1; lvl < 100; lvl++) {
|
||||
points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
output = (int) Math.floor(points / 4);
|
||||
points += floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
output = (int) floor(points / 4);
|
||||
if ((output - 1) >= exp) {
|
||||
return lvl;
|
||||
}
|
||||
|
|
@ -467,8 +470,8 @@ public final class Skills {
|
|||
int points = 0;
|
||||
int output = 0;
|
||||
for (byte lvl = 1; lvl < 100; lvl++) {
|
||||
points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
output = (int) Math.floor(points / 4);
|
||||
points += floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
output = (int) floor(points / 4);
|
||||
if ((output - 1) >= exp) {
|
||||
return lvl;
|
||||
}
|
||||
|
|
@ -485,11 +488,11 @@ public final class Skills {
|
|||
int points = 0;
|
||||
int output = 0;
|
||||
for (int lvl = 1; lvl <= level; lvl++) {
|
||||
points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
points += floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
if (lvl >= level) {
|
||||
return output;
|
||||
}
|
||||
output = (int) Math.floor(points / 4);
|
||||
output = (int) floor(points / 4);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -523,19 +526,13 @@ public final class Skills {
|
|||
if (entity instanceof NPC) {
|
||||
return ((NPC) entity).getDefinition().getCombatLevel();
|
||||
}
|
||||
int combatLevel = 0;
|
||||
int melee = staticLevels[ATTACK] + staticLevels[STRENGTH];
|
||||
int range = (int) (1.5 * staticLevels[RANGE]);
|
||||
int mage = (int) (1.5 * staticLevels[MAGIC]);
|
||||
if (melee > range && melee > mage) {
|
||||
combatLevel = melee;
|
||||
} else if (range > melee && range > mage) {
|
||||
combatLevel = range;
|
||||
} else {
|
||||
combatLevel = mage;
|
||||
}
|
||||
combatLevel = staticLevels[DEFENCE] + staticLevels[HITPOINTS] + (staticLevels[PRAYER] / 2) + (int) (1.3 * combatLevel);
|
||||
return combatLevel / 4;
|
||||
|
||||
double base = 0.25 * (staticLevels[DEFENCE] + staticLevels[HITPOINTS] + floor(0.5 * staticLevels[PRAYER]));
|
||||
double meleeBase = 0.325 * (staticLevels[ATTACK] + staticLevels[STRENGTH]);
|
||||
double rangeBase = 0.325 * (floor(staticLevels[RANGE] / 2.0) * 1.5);
|
||||
double magicBase = 0.325 * (floor(staticLevels[MAGIC] / 2.0) * 1.5);
|
||||
|
||||
return (int) (base + max(meleeBase, max(rangeBase, magicBase)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -119,6 +119,11 @@ public final class PortalOptionPlugin extends OptionHandler {
|
|||
player.getHouseManager().enter(player, buttonId == 2, true);
|
||||
break;
|
||||
case 3:
|
||||
if(player.getIronmanManager().isIronman()){
|
||||
end();
|
||||
ContentAPI.sendMessage(player, "You can't do that as an ironman.");
|
||||
return true;
|
||||
}
|
||||
ContentAPI.sendInputDialogue(player, false, "Enter friend's name:", (value) -> {
|
||||
Player p = Repository.getPlayerByName((String) value);
|
||||
if (p == null || !p.isActive()) {
|
||||
|
|
|
|||
|
|
@ -105,10 +105,12 @@ public final class SlayerManager {
|
|||
* @param npc The NPC. You're currently
|
||||
*/
|
||||
public void finalizeDeath(Player player, NPC npc) {
|
||||
player.getSkills().addExperience(Skills.SLAYER,npc.getSkills().getMaximumLifepoints());
|
||||
decrementAmount(1);
|
||||
if (!hasTask()) {
|
||||
clear();
|
||||
if(hasTask()) {
|
||||
player.getSkills().addExperience(Skills.SLAYER, npc.getSkills().getMaximumLifepoints());
|
||||
decrementAmount(1);
|
||||
}
|
||||
|
||||
if(!hasTask()){
|
||||
flags.setTaskStreak(flags.getTaskStreak() + 1);
|
||||
flags.setCompletedTasks(flags.getCompletedTasks() + 1);
|
||||
if ((flags.getCompletedTasks() > 4 || flags.canEarnPoints() ) && flags.getMaster() != Master.TURAEL && flags.getPoints() < 64000) {
|
||||
|
|
@ -251,7 +253,7 @@ public final class SlayerManager {
|
|||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasTask() {
|
||||
return getAmount() != 0;
|
||||
return getAmount() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package core.net.event;
|
|||
import core.cache.misc.buffer.ByteBufferUtils;
|
||||
import core.net.IoSession;
|
||||
import core.net.IoWriteEvent;
|
||||
import rs09.Server;
|
||||
import rs09.ServerConstants;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
|
@ -12,11 +14,6 @@ import java.nio.ByteBuffer;
|
|||
*/
|
||||
public final class MSHSWriteEvent extends IoWriteEvent {
|
||||
|
||||
/**
|
||||
* The password used to verify
|
||||
*/
|
||||
private static final String PASSWORD = "0x14ari0SSbh98989910";
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MSHSWriteEvent} {@code Object}
|
||||
* @param session The session.
|
||||
|
|
@ -28,9 +25,9 @@ public final class MSHSWriteEvent extends IoWriteEvent {
|
|||
|
||||
@Override
|
||||
public void write(IoSession session, Object context) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(2 + PASSWORD.length());
|
||||
ByteBuffer buffer = ByteBuffer.allocate(2 + ServerConstants.MS_SECRET_KEY.length());
|
||||
buffer.put((byte) 88);
|
||||
ByteBufferUtils.putString(PASSWORD, buffer);
|
||||
ByteBufferUtils.putString(ServerConstants.MS_SECRET_KEY, buffer);
|
||||
session.queue((ByteBuffer) buffer.flip());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ public final class PacketRepository {
|
|||
OUTGOING_PACKETS.put(UpdateRandomFile.class, new UpdateRandomFile()); //
|
||||
OUTGOING_PACKETS.put(InstancedLocationUpdate.class, new InstancedLocationUpdate()); //
|
||||
OUTGOING_PACKETS.put(CSConfigPacket.class, new CSConfigPacket()); //
|
||||
OUTGOING_PACKETS.put(Varbit.class, new Varbit());
|
||||
INCOMING_PACKETS.put(22, new ClientFocusPacket());
|
||||
INCOMING_PACKETS.put(93, new PingPacketHandler());
|
||||
INCOMING_PACKETS.put(44, new CommandPacket());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
public class VarbitContext implements Context {
|
||||
|
||||
Player player;
|
||||
public int varbitId;
|
||||
public int value;
|
||||
|
||||
public VarbitContext(Player player, int varbitId, int value){
|
||||
this.player = player;
|
||||
this.varbitId = varbitId;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
|
@ -266,6 +266,7 @@ public final class InteractionPacket implements IncomingPacket {
|
|||
player.debug("dir=" + object.getDirection());
|
||||
VarbitDefinition def = VarbitDefinition.forObjectID(SceneryDefinition.forId(objectId).getVarbitID());
|
||||
player.debug("Varp ID=" + def.getConfigId() + " Offset=" + def.getBitShift() + " Size=" + def.getBitSize());
|
||||
player.debug("Varbit: " + def.getId());
|
||||
if (option.getHandler() != null) {
|
||||
player.debug("Object handler: " + option.getHandler().getClass().getSimpleName());
|
||||
}
|
||||
|
|
|
|||
21
Server/src/main/java/core/net/packet/out/Varbit.java
Normal file
21
Server/src/main/java/core/net/packet/out/Varbit.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package core.net.packet.out;
|
||||
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.OutgoingPacket;
|
||||
import core.net.packet.context.VarbitContext;
|
||||
|
||||
public class Varbit implements OutgoingPacket<VarbitContext> {
|
||||
@Override
|
||||
public void send(VarbitContext varbitContext) {
|
||||
IoBuffer buffer;
|
||||
if(varbitContext.value > 255){
|
||||
buffer = new IoBuffer(84);
|
||||
buffer.putLEInt((128 | varbitContext.value) & 255);
|
||||
} else {
|
||||
buffer = new IoBuffer(37);
|
||||
buffer.put((byte) 128 | varbitContext.value);
|
||||
}
|
||||
buffer.putLEShort(varbitContext.varbitId);
|
||||
varbitContext.getPlayer().getSession().write(buffer);
|
||||
}
|
||||
}
|
||||
|
|
@ -16,10 +16,14 @@ import rs09.game.system.config.ServerConfigParser
|
|||
import rs09.game.world.GameWorld
|
||||
import rs09.game.world.repository.Repository
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.lang.management.ManagementFactory
|
||||
import java.lang.management.ThreadMXBean
|
||||
import java.net.BindException
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
|
||||
/**
|
||||
* The main class, for those that are unable to read the class' name.
|
||||
* @author Emperor
|
||||
|
|
@ -108,6 +112,13 @@ object Server {
|
|||
while(running){
|
||||
if(System.currentTimeMillis() - lastHeartbeat > 1800 && running){
|
||||
SystemLogger.logErr("Triggering reboot due to heartbeat timeout")
|
||||
SystemLogger.logErr("Creating thread dump...")
|
||||
val dump = threadDump(true, true)
|
||||
FileWriter("latestdump.txt").use {
|
||||
it.write(dump)
|
||||
it.flush()
|
||||
it.close()
|
||||
}
|
||||
exitProcess(0)
|
||||
}
|
||||
delay(625)
|
||||
|
|
@ -140,6 +151,15 @@ object Server {
|
|||
return startTime
|
||||
}
|
||||
|
||||
private fun threadDump(lockedMonitors: Boolean, lockedSynchronizers: Boolean): String? {
|
||||
val threadDump = StringBuffer(System.lineSeparator())
|
||||
val threadMXBean: ThreadMXBean = ManagementFactory.getThreadMXBean()
|
||||
for (threadInfo in threadMXBean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) {
|
||||
threadDump.append(threadInfo.toString())
|
||||
}
|
||||
return threadDump.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bastartTime.ZZ
|
||||
* @param startTime the startTime to set.
|
||||
|
|
|
|||
|
|
@ -106,6 +106,9 @@ class ServerConstants {
|
|||
@JvmField
|
||||
var GE_AUTOSTOCK_ENABLED = false
|
||||
|
||||
@JvmField
|
||||
var MS_SECRET_KEY = ""
|
||||
|
||||
//location names for the ::to command.
|
||||
val TELEPORT_DESTINATIONS = arrayOf(
|
||||
arrayOf(Location.create(2974, 4383, 2), "corp", "corporal", "corporeal"),
|
||||
|
|
@ -218,6 +221,9 @@ class ServerConstants {
|
|||
if(data.containsKey("daily_restart")){
|
||||
DAILY_RESTART = data["daily_restart"] as Boolean
|
||||
}
|
||||
|
||||
if(data.containsKey("ms_secret_key")) MS_SECRET_KEY = data["ms_secret_key"].toString()
|
||||
else MS_SECRET_KEY = "2009scape_development"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -100,14 +100,17 @@ object ServerStore {
|
|||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun JSONObject.getString(key: String): String {
|
||||
return this[key] as? String ?: "nothing"
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun JSONObject.getLong(key: String): Long {
|
||||
return this[key] as? Long ?: 0L
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun JSONObject.getBoolean(key: String): Boolean {
|
||||
return this[key] as? Boolean ?: false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package rs09.game
|
|||
|
||||
import core.cache.def.impl.VarbitDefinition
|
||||
import core.game.node.entity.player.Player
|
||||
import core.net.packet.PacketRepository
|
||||
import core.net.packet.context.VarbitContext
|
||||
import org.json.simple.JSONArray
|
||||
import org.json.simple.JSONObject
|
||||
import rs09.game.node.entity.skill.farming.FarmingPatch
|
||||
|
|
@ -32,6 +34,10 @@ class VarpManager(val player: Player) {
|
|||
get(def.configId).setVarbit(def.bitShift,value).send(player)
|
||||
}
|
||||
|
||||
fun setVarbit(varbitIndex: Int, value: Int){
|
||||
PacketRepository.send(core.net.packet.out.Varbit::class.java, VarbitContext(player, varbitIndex, value))
|
||||
}
|
||||
|
||||
fun flagSave(index: Int){
|
||||
get(index).save = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,10 +44,10 @@ class CerterEventInterface : InterfaceListener() {
|
|||
|
||||
player.packetDispatch.sendString(items[correct],CERTER_INTERFACE,optionFromIndex(correctIndex))
|
||||
|
||||
val tempOptions = falseOptions
|
||||
val tempOptions = falseOptions.toMutableList()
|
||||
val false1 = tempOptions.random()
|
||||
tempOptions.remove(false1)
|
||||
var false2 = tempOptions.random()
|
||||
while(false1 == false2) false2 = tempOptions.random()
|
||||
|
||||
player.packetDispatch.sendString(false1,CERTER_INTERFACE,optionFromIndex(indexes[0]))
|
||||
player.packetDispatch.sendString(false2,CERTER_INTERFACE,optionFromIndex(indexes[1]))
|
||||
|
|
|
|||
|
|
@ -75,10 +75,7 @@ class WorkForInteractionListener : InteractionListener() {
|
|||
|
||||
val type = typeMap[node.id] ?: return@on false
|
||||
jobId = if(type == 0) {
|
||||
var job = gatheringMap[node.id]?.random()
|
||||
while(!checkRequirement(player,job)){
|
||||
job = gatheringMap[node.id]?.random()
|
||||
}
|
||||
var job = gatheringMap[node.id]?.filter { checkRequirement(player, it) }?.random()
|
||||
amount = job?.getAmount() ?: 0
|
||||
job?.ordinal ?: 0
|
||||
} else {
|
||||
|
|
@ -111,8 +108,7 @@ class WorkForInteractionListener : InteractionListener() {
|
|||
|
||||
fun checkRequirement(player: Player, jobs: GatheringJobs?): Boolean{
|
||||
jobs ?: return true
|
||||
val requirement: Pair<Int,Int> = Pair(jobs.lvlReq,jobs.skill)
|
||||
if(player.skills.getLevel(requirement.second) < requirement.first){
|
||||
if(player.skills.getLevel(jobs.skill) < jobs.lvlReq){
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@ class DSEquipListeners : InteractionListener() {
|
|||
Items.SARADOMIN_PLATEBODY_2661,
|
||||
Items.GUTHIX_PLATEBODY_2669,
|
||||
Items.GREEN_DHIDE_BODY_1135,
|
||||
Items.BLUE_DHIDE_BODY_2499,
|
||||
Items.RED_DHIDE_BODY_2501,
|
||||
Items.BLACK_DHIDE_BODY_2503,
|
||||
Items.DHIDE_BODYG_7370,
|
||||
Items.DHIDE_BODY_G_7374,
|
||||
Items.DHIDE_BODY_T_7372,
|
||||
|
|
|
|||
|
|
@ -216,14 +216,12 @@ class BoneGrinderListener : InteractionListener() {
|
|||
|
||||
val bone = Bones.values()[player.getAttribute(LOADED_BONE_KEY,-1)]
|
||||
|
||||
player.lock()
|
||||
Pulser.submit(object : Pulse(){
|
||||
var stage = 0
|
||||
override fun pulse(): Boolean {
|
||||
when(stage++){
|
||||
0 -> {
|
||||
player.lock()
|
||||
player.animator.animate(SCOOP_ANIM)
|
||||
}
|
||||
0 -> player.animator.animate(SCOOP_ANIM)
|
||||
SCOOP_ANIM.duration -> {
|
||||
player.unlock()
|
||||
if(player.inventory.remove(Item(Items.EMPTY_POT_1931))){
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class EnchantedValleyListeners : InteractionListener() {
|
|||
fun getSpirit(player: Player): NPC {
|
||||
val level = player.properties.currentCombatLevel
|
||||
var index = Math.ceil(level / 20.0).toInt()
|
||||
if(index > TREE_SPIRIT_IDS.size) index = TREE_SPIRIT_IDS.size
|
||||
if(index >= TREE_SPIRIT_IDS.size) index = TREE_SPIRIT_IDS.size - 1
|
||||
return NPC(TREE_SPIRIT_IDS[index])
|
||||
}
|
||||
}
|
||||
|
|
@ -53,8 +53,9 @@ fun getNewTTL(): Int{
|
|||
}
|
||||
|
||||
fun getNewLoc(): Location {
|
||||
var loc = locations.random()
|
||||
while(usedLocations.contains(loc)) loc = locations.random()
|
||||
val possibleLoc = locations.toTypedArray().toMutableList()
|
||||
possibleLoc.removeAll(usedLocations)
|
||||
val loc = possibleLoc.random()
|
||||
usedLocations.add(loc)
|
||||
return loc
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ import core.game.world.map.Location
|
|||
import core.game.world.map.RegionManager
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.net.packet.PacketRepository
|
||||
import core.net.packet.context.VarbitContext
|
||||
import core.net.packet.out.Varbit
|
||||
import core.plugin.Initializable
|
||||
import core.plugin.Plugin
|
||||
import rs09.game.system.command.CommandPlugin
|
||||
|
|
@ -221,14 +224,14 @@ class VisualCommand : CommandPlugin() {
|
|||
val cfg_index = (args.getOrNull(2)?.toString()?.toInt() ?: -1)
|
||||
if(cfg_index == -1){
|
||||
ContentAPI.submitWorldPulse(object : Pulse(3, player){
|
||||
var pos = 0
|
||||
var pos = 32
|
||||
var shift = 0
|
||||
override fun pulse(): Boolean {
|
||||
for(i in 0..1999){
|
||||
player?.configManager?.forceSet(i, pos shl shift, false)
|
||||
}
|
||||
player?.sendMessage("$pos << $shift")
|
||||
if(pos++ >= 32){
|
||||
player?.sendMessage("$pos shl $shift")
|
||||
if(pos++ >= 63){
|
||||
shift += 4
|
||||
pos = 0
|
||||
}
|
||||
|
|
@ -246,6 +249,27 @@ class VisualCommand : CommandPlugin() {
|
|||
})
|
||||
}
|
||||
}
|
||||
"setbit" -> {
|
||||
if (args!!.size < 2) {
|
||||
player!!.debug("syntax error: bit value")
|
||||
return true
|
||||
}
|
||||
var bit = toInteger(args[0]!!)
|
||||
var value = toInteger(args[1]!!)
|
||||
var val2 = toInteger(args[2]!!)
|
||||
player!!.debug("$value $val2")
|
||||
PacketRepository.send(Varbit::class.java, VarbitContext(player, value, val2))
|
||||
return true
|
||||
}
|
||||
"setbits" -> {
|
||||
args ?: return false
|
||||
val start = toInteger(args[1]!!)
|
||||
val end = toInteger(args[2]!!)
|
||||
val value = toInteger(args[3]!!)
|
||||
for(i in start until end){
|
||||
player?.varpManager?.setVarbit(i, value)
|
||||
}
|
||||
}
|
||||
"loop_anim_on_i" -> {
|
||||
var anim = toInteger(args!![1]!!)
|
||||
ContentAPI.submitWorldPulse(object : Pulse(3){
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ class MajorUpdateWorker {
|
|||
var started = false
|
||||
val sequence = UpdateSequence()
|
||||
val sdf = SimpleDateFormat("HHmmss")
|
||||
fun start() = GlobalScope.launch {
|
||||
val worker = Thread {
|
||||
Thread.currentThread().name = "Major Update Worker"
|
||||
started = true
|
||||
delay(600L)
|
||||
Thread.sleep(600L)
|
||||
while(true){
|
||||
val start = System.currentTimeMillis()
|
||||
val rmlist = ArrayList<Pulse>()
|
||||
|
|
@ -94,7 +95,12 @@ class MajorUpdateWorker {
|
|||
}
|
||||
|
||||
val end = System.currentTimeMillis()
|
||||
delay(max(600 - (end - start), 0))
|
||||
Thread.sleep(max(600 - (end - start), 0))
|
||||
}
|
||||
}
|
||||
fun start() {
|
||||
if(!started){
|
||||
worker.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -43,7 +43,8 @@
|
|||
"database_username": "root",
|
||||
"database_password": "",
|
||||
"database_address": "127.0.0.1",
|
||||
"database_port": "3306"
|
||||
"database_port": "3306",
|
||||
"ms_secret_key": "2009scape_development"
|
||||
},
|
||||
|
||||
"PluginToggles": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue