Skip to content

Commit

Permalink
Use quest slot instead of keeping in memory
Browse files Browse the repository at this point in the history
  • Loading branch information
AntumDeluge committed May 3, 2024
1 parent 558649d commit e4afdb6
Showing 1 changed file with 55 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,76 +11,92 @@
***************************************************************************/
package games.stendhal.server.maps.kikareukin.islands;

import java.util.HashMap;
import java.util.Map;

import games.stendhal.common.Level;
import games.stendhal.common.MathHelper;
import games.stendhal.common.NotificationType;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.core.events.TurnListener;
import games.stendhal.server.core.events.TurnNotifier;
import games.stendhal.server.entity.npc.action.IncrementQuestAction;
import games.stendhal.server.entity.player.Player;
import marauroa.common.Pair;


public class HeavenGateKeeper {

/** Slot name used for tracking requests. */
private static final String SLOT = "heaven_gatekeeper";
/** Name of entity that messages player. */
private static final String ENTITY_NAME = "Kikareukin's Gatekeeper";
/** Number of requests allowed before being punished. */
private static final short REQUEST_LIMIT = 3;
/** Time period in which player requests are tracked (4 days). */
private static final long TIME_BUFFER = MathHelper.MILLISECONDS_IN_ONE_DAY * 4;
/** XP modifier for trying to requesting too often (15% of excess). */
private static final float XP_MODIFIER = 0.15f;

// FIXME: would it be better to store in database than using memory?
private static Map<String, Pair<Long, Integer>> visitors = new HashMap<>();


private static Pair<Long, Integer> getVisitorInfo(final String name) {
if (HeavenGateKeeper.visitors.containsKey(name)) {
return HeavenGateKeeper.visitors.get(name);
/**
* Increments number of requests player has made.
*
* @param player
* Player requesting entrance.
*/
private static void addRequest(final Player player) {
final long timeFromRequestStart = System.currentTimeMillis() - HeavenGateKeeper.getRequestTime(player);
if (timeFromRequestStart > HeavenGateKeeper.TIME_BUFFER) {
// first request or time limit expired so reset so player isn't unnecessarily punished
player.setQuest(HeavenGateKeeper.SLOT, System.currentTimeMillis() + ";1");
} else {
new IncrementQuestAction(HeavenGateKeeper.SLOT, 1, 1).fire(player, null, null);
}
return HeavenGateKeeper.createVisitorInfo(name);
}

private static Pair<Long, Integer> createVisitorInfo(final String name) {
final Pair<Long, Integer> request = new Pair<>(System.currentTimeMillis(), 0);
HeavenGateKeeper.visitors.put(name, request);
return request;
}

private static void addRequest(final String name) {
final Pair<Long, Integer> visitorInfo = HeavenGateKeeper.getVisitorInfo(name);
visitorInfo.setSecond(visitorInfo.second() + 1);
visitors.put(name, visitorInfo);
}

private static long getRequestTime(final String name) {
return HeavenGateKeeper.getVisitorInfo(name).first();
/**
* Retrieves the time period beginning when player made initial request.
*
* @param player
* Player requesting entrance.
* @return
* Time of initial request.
*/
private static long getRequestTime(final Player player) {
return MathHelper.parseLongDefault(player.getQuest(HeavenGateKeeper.SLOT, 0), 0);
}

private static int getRequestCount(final String name) {
return HeavenGateKeeper.getVisitorInfo(name).second();
/**
* Retrieves number of request player has made in the current time period.
*
* @param player
* Player requesting entrance.
* @return
* Request count.
*/
private static int getRequestCount(final Player player) {
return MathHelper.parseIntDefault(player.getQuest(HeavenGateKeeper.SLOT, 1), 0);
}

/**
* Punishment from heaven.
*
* - sent to afterlife
* - loses all but 1 HP
* - loses 15% of excess XP
*
* TODO:
* - add lightning (spell effect)
* - play thunder sound
*
* @param player
* Player being punished.
*/
private static void punish(final Player player) {
// TODO:
// - add lightning (spell effect)
// - play thunder sound

// set player's HP to 1 & send to afterlife
// send to afterlife
final StendhalRPZone afterlife = SingletonRepository.getRPWorld().getZone("int_afterlife");
if (afterlife != null) {
player.teleport(afterlife, 31, 23, player.getDirection(), null);
}
// set HP to 1 & subtract XP
final int xpStart = player.getXP();
// a percentage of XP based on difference requirement to next level (levels can be lost)
//final int xpDiff = (int) Math.floor(Level.getXPDiff(player.getLevel()-1) * HeavenGateKeeper.XP_MODIFIER);
Expand Down Expand Up @@ -116,18 +132,12 @@ private static void punish(final Player player) {
* Checks if player violates visit limit.
*
* @param player
* Name of player requesting entrance.
* Player requesting entrance.
* @return
* `true` if player has made more than 3 requests within 3 days.
* `true` if player has made more than 3 requests within 4 days.
*/
private static boolean inViolation(final String name) {
final long timeFromRequestStart = System.currentTimeMillis() - HeavenGateKeeper.getRequestTime(name);
if (timeFromRequestStart > HeavenGateKeeper.TIME_BUFFER) {
// reset request state so player doesn't get unnecessarily punished
HeavenGateKeeper.createVisitorInfo(name);
return false;
}
return HeavenGateKeeper.getRequestCount(name) > HeavenGateKeeper.REQUEST_LIMIT;
private static boolean inViolation(final Player player) {
return HeavenGateKeeper.getRequestCount(player) > HeavenGateKeeper.REQUEST_LIMIT;
}

/**
Expand All @@ -139,17 +149,16 @@ private static boolean inViolation(final String name) {
* Whether player can enter.
*/
public static boolean requestEntrance(final Player player) {
final String name = player.getName();
HeavenGateKeeper.addRequest(name);
if (HeavenGateKeeper.inViolation(name)) {
HeavenGateKeeper.addRequest(player);
if (HeavenGateKeeper.inViolation(player)) {
// first delay is to notify player, second is to apply punishment
final TurnNotifier notifier = SingletonRepository.getTurnNotifier();
final TurnListener listener = new TurnListener() {
private boolean notified = false;
@Override
public void onTurnReached(int currentTurn) {
if (!notified) {
player.sendPrivateText(NotificationType.PRIVMSG, "Kikareukin's Gatekeeper",
player.sendPrivateText(NotificationType.PRIVMSG, HeavenGateKeeper.ENTITY_NAME,
"You have worn out your welcome and shall be punished for your greed!");
notified = true;
notifier.notifyInTurns(10, this);
Expand Down

0 comments on commit e4afdb6

Please sign in to comment.