Rewrote pet back end to use a more authentic system
Pets can now stack Fixes a bug where a pet could get reset to 0 hunger and growth when dropped Player save version migration messages are no longer shown Pets now morph into adults in-place
This commit is contained in:
@@ -18,7 +18,7 @@ class ServerConstants {
|
||||
var NOAUTH_DEFAULT_ADMIN: Boolean = true
|
||||
|
||||
@JvmField
|
||||
var CURRENT_SAVEFILE_VERSION = 1
|
||||
var CURRENT_SAVEFILE_VERSION = 2
|
||||
|
||||
@JvmField
|
||||
var DAILY_ACCOUNT_LIMIT = 3
|
||||
|
||||
@@ -326,6 +326,7 @@ fun addItem(player: Player, id: Int, amount: Int = 1, container: Container = Con
|
||||
* @param player the player whose container to modify
|
||||
* @param slot the slot to use
|
||||
* @param item the item to replace the slot with
|
||||
* @param currentItem the current item that is being replaced
|
||||
* @param container the Container to modify
|
||||
* @return the item that was previously in the slot, or null if none.
|
||||
*/
|
||||
@@ -358,6 +359,41 @@ fun replaceSlot(player: Player, slot: Int, item: Item, currentItem: Item? = null
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all items a player owns anywhere (equipment, inventory, bank, second bank)
|
||||
* @param player the player whose inventory to remove the item from
|
||||
* @param itemId the item ID to replace
|
||||
* @param replaceId the replacement item ID
|
||||
* @author Player Name
|
||||
*/
|
||||
fun replaceAllItems(player: Player, itemId: Int, replaceId: Int) {
|
||||
val item = Item(itemId)
|
||||
for (container in arrayOf(player.inventory, player.equipment, player.bankPrimary, player.bankSecondary)) {
|
||||
val hasItems = container.getAll(item)
|
||||
if (!item.definition.isStackable && (container == player.inventory || container == player.equipment)) {
|
||||
for (target in hasItems) {
|
||||
val newItem = Item(replaceId, target.amount)
|
||||
container.replace(newItem, target.slot, true)
|
||||
}
|
||||
} else {
|
||||
if (hasItems.size > 0) {
|
||||
val target = hasItems[0]
|
||||
var count = 0
|
||||
for (x in hasItems) {
|
||||
count += x.amount
|
||||
}
|
||||
val newItem = Item(replaceId, count)
|
||||
container.replace(newItem, target.slot, true)
|
||||
}
|
||||
if (hasItems.size > 1) {
|
||||
for (i in 1 until hasItems.size) {
|
||||
container.remove(hasItems[i], hasItems[i].slot, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item with a variable quantity or drop it if a player does not have enough space
|
||||
* @param player the player whose inventory to add to
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
package core.game.node.entity.npc;
|
||||
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.game.dialogue.DialoguePlugin;
|
||||
import content.global.skill.summoning.familiar.Familiar;
|
||||
import content.global.skill.summoning.pet.Pets;
|
||||
import core.game.interaction.OptionHandler;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.plugin.Plugin;
|
||||
import core.plugin.ClassScanner;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* A superclass plugin for any pets that have a metamorphosis option.
|
||||
* @author Empathy
|
||||
*
|
||||
*/
|
||||
public abstract class Metamorphosis extends OptionHandler {
|
||||
|
||||
/**
|
||||
* The ids of the possible npcs to metamorph into.
|
||||
*/
|
||||
protected int[] ids;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Metamorphosis} {@code Object}.
|
||||
* @param ids the id to transform.
|
||||
*/
|
||||
public Metamorphosis(int...ids) {
|
||||
this.ids = ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* The dialogue plugin for the pet.
|
||||
* @return the plugin.
|
||||
*/
|
||||
public abstract DialoguePlugin getDialoguePlugin();
|
||||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
for (int id : getIds()) {
|
||||
NPCDefinition.forId(id).getHandlers().put("option:metamorphosis", this);
|
||||
}
|
||||
if (getDialoguePlugin() != null) {
|
||||
ClassScanner.definePlugin(getDialoguePlugin());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(Player player, Node node, String option) {
|
||||
Familiar familiar = (Familiar) node;
|
||||
switch (option) {
|
||||
case "metamorphosis":
|
||||
if (player.getFamiliarManager().isOwner(familiar)) {
|
||||
int newNpc = player.getFamiliarManager().getFamiliar().getId();
|
||||
while (newNpc == player.getFamiliarManager().getFamiliar().getId()) {
|
||||
newNpc = getRandomNpcId();
|
||||
}
|
||||
for (Pets p : Pets.values()) {
|
||||
if (p.getBabyNpcId() == newNpc) {
|
||||
player.getFamiliarManager().morphPet(new Item(p.getBabyItemId()), false, player.getFamiliarManager().getFamiliar().getLocation());
|
||||
break;
|
||||
}
|
||||
}
|
||||
player.getPacketDispatch().sendMessage("You transform your " + player.getFamiliarManager().getFamiliar().getName() + "!");
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("This is not your familiar.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a random npc id.
|
||||
* @return
|
||||
*/
|
||||
public int getRandomNpcId() {
|
||||
int i = RandomFunction.getRandom(getIds().length - 1);
|
||||
return getIds()[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the npc ids.
|
||||
* @return the id.
|
||||
*/
|
||||
public int[] getIds() {
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ class PlayerSaveParser(val player: Player) {
|
||||
}
|
||||
|
||||
fun parseData() {
|
||||
parseVersion()
|
||||
parseCore()
|
||||
parseAttributes()
|
||||
parseSkills()
|
||||
@@ -77,7 +78,6 @@ class PlayerSaveParser(val player: Player) {
|
||||
parseStatistics()
|
||||
parseAchievements()
|
||||
parsePouches()
|
||||
parseVersion()
|
||||
}
|
||||
|
||||
fun runContentHooks()
|
||||
|
||||
@@ -36,6 +36,7 @@ class PlayerSaver (val player: Player){
|
||||
}
|
||||
fun populate(): JSONObject {
|
||||
val saveFile = JSONObject()
|
||||
saveVersion(saveFile)
|
||||
saveCoreData(saveFile)
|
||||
saveSkills(saveFile)
|
||||
saveSettings(saveFile)
|
||||
@@ -56,7 +57,6 @@ class PlayerSaver (val player: Player){
|
||||
saveStatManager(saveFile)
|
||||
saveAttributes(saveFile)
|
||||
savePouches(saveFile)
|
||||
saveVersion(saveFile)
|
||||
contentHooks.forEach { it.savePlayer(player, saveFile) }
|
||||
return saveFile
|
||||
}
|
||||
@@ -278,17 +278,21 @@ class PlayerSaver (val player: Player){
|
||||
|
||||
fun saveFamiliarManager(root: JSONObject){
|
||||
val familiarManager = JSONObject()
|
||||
val petDetails = JSONArray()
|
||||
val petDetails = JSONObject()
|
||||
player.familiarManager.petDetails.map {
|
||||
val detail = JSONObject()
|
||||
detail.put("petId",it.key.toString())
|
||||
detail.put("hunger",it.value.hunger.toString())
|
||||
detail.put("growth",it.value.growth.toString())
|
||||
petDetails.add(detail)
|
||||
val petId = it.key
|
||||
val petData = JSONArray()
|
||||
for (v in it.value) {
|
||||
val pet = JSONObject()
|
||||
pet.put("hunger",v.hunger.toString())
|
||||
pet.put("growth",v.growth.toString())
|
||||
petData.add(pet)
|
||||
}
|
||||
petDetails.put(petId.toString(), petData)
|
||||
}
|
||||
familiarManager.put("petDetails",petDetails)
|
||||
if(player.familiarManager.hasPet()){
|
||||
familiarManager.put("currentPet",(player.familiarManager.familiar as Pet).getItemIdHash().toString())
|
||||
familiarManager.put("currentPet",(player.familiarManager.familiar as Pet).getItemId().toString())
|
||||
} else if (player.familiarManager.hasFamiliar()){
|
||||
val familiar = JSONObject()
|
||||
familiar.put("originalId",player.familiarManager.familiar.originalId.toString())
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
package core.game.node.entity.player.info.login
|
||||
|
||||
import content.global.skill.summoning.pet.Pets
|
||||
import core.ServerConstants
|
||||
import core.api.*
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
|
||||
|
||||
/**
|
||||
* Runs one-time save-version-related hooks.
|
||||
* @author Player Name
|
||||
*/
|
||||
|
||||
class SaveVersionHooks : LoginListener {
|
||||
|
||||
override fun login(player: Player) {
|
||||
if (player.version < ServerConstants.CURRENT_SAVEFILE_VERSION) {
|
||||
sendMessage(player, "<col=CC6600>Migrating save file version ${player.version} to current save file version ${ServerConstants.CURRENT_SAVEFILE_VERSION}.</col>")
|
||||
|
||||
// Perform actual migrations
|
||||
if (player.version < 1) { // GL #1811
|
||||
if (player.version < 1) { // GL !1811
|
||||
// Give out crafting hoods if the player bought any crafting capes when the hoods were not obtainable
|
||||
var hasHoods = 0
|
||||
var hasCapes = 0
|
||||
@@ -60,10 +57,18 @@ class SaveVersionHooks : LoginListener {
|
||||
}
|
||||
}
|
||||
|
||||
// Finish up
|
||||
if (player.version < 2) { //GL !1799
|
||||
// Most of the migration for this MR happens in FamiliarManager.java, but we fix up any pet items here
|
||||
val pets = Pets.values()
|
||||
for (pet in pets) {
|
||||
for (id in arrayOf(pet.babyItemId, pet.grownItemId, pet.overgrownItemId)) {
|
||||
replaceAllItems(player, id, id)
|
||||
// The trick here is that replaceAllItems ignores the item charge value, and will hence cause it to be lost, making all pets authentically stack again
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player.version = ServerConstants.CURRENT_SAVEFILE_VERSION
|
||||
sendMessage(player, "<col=CC6600>Save file migration complete. Happy scaping!</col>")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -196,14 +196,6 @@ public class Item extends Node{
|
||||
return idHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id hash.
|
||||
* @param hash the hash to set
|
||||
*/
|
||||
public void setIdHash(int hash) {
|
||||
this.idHash = hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the item has a wrapper plugin.
|
||||
* @return {@code True} if so.
|
||||
|
||||
Reference in New Issue
Block a user