diff --git a/Server/src/main/core/api/utils/Permadeath.kt b/Server/src/main/core/api/utils/Permadeath.kt new file mode 100644 index 000000000..d74c6fef9 --- /dev/null +++ b/Server/src/main/core/api/utils/Permadeath.kt @@ -0,0 +1,47 @@ +package core.api.utils.Permadeath + +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.VarpManager +import core.game.node.entity.player.info.login.PlayerSaver +import core.game.node.entity.player.link.SavedData +import core.game.node.entity.player.link.diary.DiaryType +import core.game.node.entity.player.link.quest.QuestRepository +import core.game.node.entity.skill.Skills +import core.game.world.map.Location + +fun permadeath(target: Player) { + teleport(target, Location.create(3094, 3107, 0)) + target.equipment.clear() + target.inventory.clear() + if (isUsingSecondaryBankAccount(target)) { + toggleBankAccount(target) + } + target.bank.clear() + target.bankSecondary.clear() + target.skills = Skills(target) + target.clearAttributes() + target.savedData = SavedData(target) + target.questRepository = QuestRepository(target) + target.varpManager = VarpManager(target) + target.varpMap.clear() + target.saveVarp.clear() + if (target.familiarManager.hasFamiliar()) { + target.familiarManager.dismiss() + } + val petKeys = target.familiarManager.petDetails.keys.toList() + for (key in petKeys) { + target.familiarManager.removeDetails(key) + } + for (type in DiaryType.values()) { + val diary = target.achievementDiaryManager.getDiary(type) + for (level in 0 until diary.levelStarted.size) { + for (task in 0 until diary.taskCompleted[level].size) { + diary.resetTask(target, level, task) + } + } + } + target.musicPlayer.clearUnlocked() + PlayerSaver(target).save() + target.clear() +} diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index 330f2fb0e..a55ff25a8 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -69,7 +69,6 @@ import core.game.node.entity.combat.CombatSwingHandler; import content.global.handlers.item.equipment.EquipmentDegrader; import core.game.node.entity.combat.graves.Grave; import core.game.node.entity.combat.graves.GraveController; -import core.game.node.entity.player.info.login.PlayerSaver; import core.game.node.entity.state.State; import core.game.node.entity.state.StateRepository; import core.game.world.GameWorld; @@ -88,6 +87,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; import static core.api.ContentAPIKt.*; +import static core.api.utils.Permadeath.PermadeathKt.permadeath; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_BASE; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_DEATHS; import static core.tools.GlobalsKt.colorize; @@ -315,7 +315,7 @@ public class Player extends Entity { public byte[] opCounts = new byte[255]; - public int invalidPacketCount = 0; + public int invalidPacketCount = 0; /** * Constructs a new {@code Player} {@code Object}. @@ -597,7 +597,7 @@ public class Player extends Entity { @Override public void finalizeDeath(Entity killer) { - if (!isPlaying()) return; //if the player has already been full cleared, it has already disconnected. This code is probably getting called because something is maintaining a stale reference. + if (!isPlaying()) return; //if the player has already been full cleared, it has already disconnected. This code is probably getting called because something is maintaining a stale reference. GlobalStats.incrementDeathCount(); settings.setSpecialEnergy(100); settings.updateRunEnergy(settings.getRunEnergy() - 100); @@ -626,19 +626,7 @@ public class Player extends Entity { String gender = this.isMale() ? "man " : "woman "; if (getAttributes().containsKey("permadeath")) { Repository.sendNews("Permadeath Hardcore Iron" + gender + " " + this.getUsername() + " has fallen. Total Level: " + this.getSkills().getTotalLevel()); // Not enough room for XP - equipment.clear(); - inventory.clear(); - bank.clear(); - skills = new Skills(this); - clearAttributes(); - setAttribute("/save:permadeath", true); - savedData = new SavedData(this); - questRepository = new QuestRepository(this); - varpManager = new VarpManager(this); - varpMap.clear(); - saveVarp.clear(); - new PlayerSaver(this).save(); - clear(); + permadeath(this); return; } else { Repository.sendNews("Hardcore Iron " + gender + " " + this.getUsername() + " has fallen. Total Level: " + this.getSkills().getTotalLevel()); // Not enough room for XP diff --git a/Server/src/main/core/game/node/entity/player/link/music/MusicPlayer.java b/Server/src/main/core/game/node/entity/player/link/music/MusicPlayer.java index b9874f71b..77f55b618 100644 --- a/Server/src/main/core/game/node/entity/player/link/music/MusicPlayer.java +++ b/Server/src/main/core/game/node/entity/player/link/music/MusicPlayer.java @@ -95,6 +95,13 @@ public final class MusicPlayer { } } + /** + * Clears the unlocked songs. This should only be used in the permadeath code. + */ + public void clearUnlocked() { + this.unlocked.clear(); + } + /** * Checks if the player has enough songs unlocked for the Air guitar emote. * @return {@code True} if so. diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index bf9ba822c..7a96b1381 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -1,42 +1,39 @@ package core.game.system.command.sets +import content.global.handlers.iface.RulesAndInfo +import content.global.skill.farming.timers.* +import content.minigame.fishingtrawler.TrawlerLoot +import content.region.misthalin.draynor.quest.anma.AnmaCutscene +import core.ServerConstants import core.api.* -import core.api.InputType +import core.api.utils.Permadeath.permadeath import core.cache.def.impl.NPCDefinition import core.cache.def.impl.SceneryDefinition import core.cache.def.impl.VarbitDefinition +import core.game.bots.AIRepository import core.game.component.Component +import core.game.ge.GrandExchange import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.entity.player.info.Rights import core.game.node.entity.skill.Skills import core.game.node.item.Item import core.game.node.scenery.Scenery +import core.game.system.command.CommandMapping +import core.game.system.command.Privilege import core.game.system.communication.CommunicationInfo import core.game.world.map.RegionManager import core.game.world.map.build.DynamicRegion +import core.game.world.repository.Repository import core.plugin.Initializable +import core.tools.Log import core.tools.StringUtils import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.rs09.consts.Components -import core.ServerConstants -import core.game.bots.AIRepository -import core.api.utils.PlayerCamera -import content.global.ame.RandomEvents -import content.region.misthalin.draynor.quest.anma.AnmaCutscene -import core.game.ge.GrandExchange -import content.global.handlers.iface.RulesAndInfo -import content.minigame.fishingtrawler.TrawlerLoot -import core.game.system.command.CommandMapping -import core.game.system.command.Privilege -import core.game.world.repository.Repository -import core.tools.Log -import core.tools.colorize import java.awt.HeadlessException import java.awt.Toolkit import java.awt.datatransfer.StringSelection -import content.global.skill.farming.timers.* @Initializable class MiscCommandSet : CommandSet(Privilege.ADMIN){ @@ -377,6 +374,22 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ } } + /** + * Permadeaths a player, resetting their save + */ + define("permadeath", Privilege.ADMIN, "::permadeath PLAYER", "Permadeaths PLAYER (self if omitted), completely wiping their save."){player,args -> + var target = player + if (args.size > 1) { + val n = args.slice(1 until args.size).joinToString("_") + val foundtarget = Repository.getPlayerByName(n) + if (foundtarget == null) { + reject(player, "Invalid player \"${n}\" or player not online") + } + target = foundtarget!! + } + permadeath(target) + } + define("log", Privilege.ADMIN){player,_ -> var log: ArrayList? = player.getAttribute("loc-log") log = log ?: ArrayList()