Commit 65861c3c authored by Akka's avatar Akka Committed by GitHub
Browse files

Merge pull request #7 from Grasscutters/development

Development
parents c2d2a37f 176f3e91
package emu.grasscutter.game.managers.StaminaManager;
public enum ConsumptionType {
None(0),
// consume
CLIMB_START(-500),
CLIMBING(-150),
CLIMB_JUMP(-2500),
SPRINT(-1800),
DASH(-360),
FLY(-60),
SWIM_DASH_START(-20),
SWIM_DASH(-204),
SWIMMING(-80), // TODO: Slow swimming is handled per movement, not per second. Movement frequency depends on gender/age/height.
FIGHT(0), // See StaminaManager.getFightConsumption()
// restore
STANDBY(500),
RUN(500),
WALK(500),
STANDBY_MOVE(500),
POWERED_FLY(500);
public final int amount;
ConsumptionType(int amount) {
this.amount = amount;
}
}
\ No newline at end of file
# Stamina Manager
---
## UpdateStamina
```java
// will use consumption.consumptionType as reason
public int updateStaminaRelative(GameSession session, Consumption consumption);
```
```java
public int updateStaminaAbsolute(GameSession session, String reason, int newStamina)
```
---
## Pause and Resume
```java
public void startSustainedStaminaHandler()
```
```java
public void stopSustainedStaminaHandler()
```
---
## Stamina change listeners and intercepting
### BeforeUpdateStaminaListener
```java
import emu.grasscutter.game.managers.StaminaManager.BeforeUpdateStaminaListener;
// Listener sample: plugin disable CLIMB_JUMP stamina cost.
private class MyClass implements BeforeUpdateStaminaListener {
// Make your class implement the listener, and pass in your class as a listener.
public MyClass() {
getStaminaManager().registerBeforeUpdateStaminaListener("myClass", this);
}
@Override
public boolean onBeforeUpdateStamina(String reason, int newStamina) {
// do not intercept this update
return false;
}
@Override
public boolean onBeforeUpdateStamina(String reason, Consumption consumption) {
// Try to intercept if this update is CLIMB_JUMP
if (consumption.consumptionType == ConsumptionType.CLIMB_JUMP) {
return true;
}
// If it is not CLIMB_JUMP, do not intercept.
return false;
}
}
```
### AfterUpdateStaminaListener
```java
import emu.grasscutter.game.managers.StaminaManager.AfterUpdateStaminaListener;
// Listener sample: plugin listens for changes already made.
private class MyClass implements AfterUpdateStaminaListener {
// Make your class implement the listener, and pass in your class as a listener.
public MyClass() {
registerAfterUpdateStaminaListener("myClass", this);
}
@Override
public void onAfterUpdateStamina(String reason, int newStamina) {
// ...
}
}
```
\ No newline at end of file
...@@ -14,6 +14,7 @@ import emu.grasscutter.game.avatar.AvatarStorage; ...@@ -14,6 +14,7 @@ import emu.grasscutter.game.avatar.AvatarStorage;
import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.EntityItem; import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.GameEntity; import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.expedition.ExpeditionInfo;
import emu.grasscutter.game.friends.FriendsList; import emu.grasscutter.game.friends.FriendsList;
import emu.grasscutter.game.friends.PlayerProfile; import emu.grasscutter.game.friends.PlayerProfile;
import emu.grasscutter.game.gacha.PlayerGachaInfo; import emu.grasscutter.game.gacha.PlayerGachaInfo;
...@@ -21,8 +22,8 @@ import emu.grasscutter.game.inventory.GameItem; ...@@ -21,8 +22,8 @@ import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.inventory.Inventory;
import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.mail.Mail;
import emu.grasscutter.game.mail.MailHandler; import emu.grasscutter.game.mail.MailHandler;
import emu.grasscutter.game.managers.MovementManager.MovementManager; import emu.grasscutter.game.managers.StaminaManager.StaminaManager;
import emu.grasscutter.game.managers.SotSManager.SotSManager; import emu.grasscutter.game.managers.SotSManager;
import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
...@@ -51,6 +52,7 @@ import emu.grasscutter.server.packet.send.*; ...@@ -51,6 +52,7 @@ import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.utils.DateHelper; import emu.grasscutter.utils.DateHelper;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.MessageHandler; import emu.grasscutter.utils.MessageHandler;
import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
...@@ -60,9 +62,6 @@ import java.util.concurrent.LinkedBlockingQueue; ...@@ -60,9 +62,6 @@ import java.util.concurrent.LinkedBlockingQueue;
@Entity(value = "players", useDiscriminator = false) @Entity(value = "players", useDiscriminator = false)
public class Player { public class Player {
@Transient private static int GlobalMaximumSpringVolume = 8500000;
@Transient private static int GlobalMaximumStamina = 24000;
@Id private int id; @Id private int id;
@Indexed(options = @IndexOptions(unique = true)) private String accountId; @Indexed(options = @IndexOptions(unique = true)) private String accountId;
...@@ -102,6 +101,7 @@ public class Player { ...@@ -102,6 +101,7 @@ public class Player {
private ArrayList<AvatarProfileData> shownAvatars; private ArrayList<AvatarProfileData> shownAvatars;
private Set<Integer> rewardedLevels; private Set<Integer> rewardedLevels;
private ArrayList<ShopLimit> shopLimit; private ArrayList<ShopLimit> shopLimit;
private Map<Long, ExpeditionInfo> expeditionInfo;
private int sceneId; private int sceneId;
private int regionId; private int regionId;
...@@ -129,7 +129,7 @@ public class Player { ...@@ -129,7 +129,7 @@ public class Player {
@Transient private final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler; @Transient private final InvokeHandler<AbilityInvokeEntry> clientAbilityInitFinishHandler;
private MapMarksManager mapMarksManager; private MapMarksManager mapMarksManager;
@Transient private MovementManager movementManager; @Transient private StaminaManager staminaManager;
private long springLastUsed; private long springLastUsed;
...@@ -141,6 +141,7 @@ public class Player { ...@@ -141,6 +141,7 @@ public class Player {
this.avatars = new AvatarStorage(this); this.avatars = new AvatarStorage(this);
this.friendsList = new FriendsList(this); this.friendsList = new FriendsList(this);
this.mailHandler = new MailHandler(this); this.mailHandler = new MailHandler(this);
this.towerManager = new TowerManager(this);
this.pos = new Position(); this.pos = new Position();
this.rotation = new Position(); this.rotation = new Position();
this.properties = new HashMap<>(); this.properties = new HashMap<>();
...@@ -171,9 +172,10 @@ public class Player { ...@@ -171,9 +172,10 @@ public class Player {
this.moonCardGetTimes = new HashSet<>(); this.moonCardGetTimes = new HashSet<>();
this.shopLimit = new ArrayList<>(); this.shopLimit = new ArrayList<>();
this.expeditionInfo = new HashMap<>();
this.messageHandler = null; this.messageHandler = null;
this.mapMarksManager = new MapMarksManager(); this.mapMarksManager = new MapMarksManager();
this.movementManager = new MovementManager(this); this.staminaManager = new StaminaManager(this);
this.sotsManager = new SotSManager(this); this.sotsManager = new SotSManager(this);
} }
...@@ -186,7 +188,6 @@ public class Player { ...@@ -186,7 +188,6 @@ public class Player {
this.nickname = "Traveler"; this.nickname = "Traveler";
this.signature = ""; this.signature = "";
this.teamManager = new TeamManager(this); this.teamManager = new TeamManager(this);
this.towerManager = new TowerManager(this);
this.birthday = new PlayerBirthday(); this.birthday = new PlayerBirthday();
this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1); this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1);
this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1); this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1);
...@@ -202,7 +203,7 @@ public class Player { ...@@ -202,7 +203,7 @@ public class Player {
this.getRotation().set(0, 307, 0); this.getRotation().set(0, 307, 0);
this.messageHandler = null; this.messageHandler = null;
this.mapMarksManager = new MapMarksManager(); this.mapMarksManager = new MapMarksManager();
this.movementManager = new MovementManager(this); this.staminaManager = new StaminaManager(this);
this.sotsManager = new SotSManager(this); this.sotsManager = new SotSManager(this);
} }
...@@ -674,6 +675,28 @@ public class Player { ...@@ -674,6 +675,28 @@ public class Player {
session.send(new PacketCardProductRewardNotify(getMoonCardRemainDays())); session.send(new PacketCardProductRewardNotify(getMoonCardRemainDays()));
} }
public Map<Long, ExpeditionInfo> getExpeditionInfo() {
return expeditionInfo;
}
public void addExpeditionInfo(long avaterGuid, int expId, int hourTime, int startTime){
ExpeditionInfo exp = new ExpeditionInfo();
exp.setExpId(expId);
exp.setHourTime(hourTime);
exp.setState(1);
exp.setStartTime(startTime);
expeditionInfo.put(avaterGuid, exp);
}
public void removeExpeditionInfo(long avaterGuid){
expeditionInfo.remove(avaterGuid);
}
public ExpeditionInfo getExpeditionInfo(long avaterGuid){
return expeditionInfo.get(avaterGuid);
}
public List<ShopLimit> getShopLimit() { public List<ShopLimit> getShopLimit() {
return shopLimit; return shopLimit;
} }
...@@ -849,11 +872,11 @@ public class Player { ...@@ -849,11 +872,11 @@ public class Player {
} }
public void onPause() { public void onPause() {
getStaminaManager().stopSustainedStaminaHandler();
} }
public void onUnpause() { public void onUnpause() {
getStaminaManager().startSustainedStaminaHandler();
} }
public void sendPacket(BasePacket packet) { public void sendPacket(BasePacket packet) {
...@@ -998,7 +1021,7 @@ public class Player { ...@@ -998,7 +1021,7 @@ public class Player {
return mapMarksManager; return mapMarksManager;
} }
public MovementManager getMovementManager() { return movementManager; } public StaminaManager getStaminaManager() { return staminaManager; }
public SotSManager getSotSManager() { return sotsManager; } public SotSManager getSotSManager() { return sotsManager; }
...@@ -1030,6 +1053,22 @@ public class Player { ...@@ -1030,6 +1053,22 @@ public class Player {
this.resetSendPlayerLocTime(); this.resetSendPlayerLocTime();
} }
} }
// Expedition
var timeNow = Utils.getCurrentSeconds();
var needNotify = false;
for (Long key : expeditionInfo.keySet()) {
ExpeditionInfo e = expeditionInfo.get(key);
if(e.getState() == 1){
if(timeNow - e.getStartTime() >= e.getHourTime() * 60 * 60){
e.setState(2);
needNotify = true;
}
}
}
if(needNotify){
this.save();
this.sendPacket(new PacketAvatarExpeditionDataNotify(this));
}
} }
...@@ -1057,9 +1096,6 @@ public class Player { ...@@ -1057,9 +1096,6 @@ public class Player {
if (this.getProfile().getUid() == 0) { if (this.getProfile().getUid() == 0) {
this.getProfile().syncWithCharacter(this); this.getProfile().syncWithCharacter(this);
} }
if (this.getTowerManager() == null) {
this.towerManager = new TowerManager(this);
}
// Check if player object exists in server // Check if player object exists in server
// TODO - optimize // TODO - optimize
...@@ -1112,8 +1148,11 @@ public class Player { ...@@ -1112,8 +1148,11 @@ public class Player {
} }
public void onLogout() { public void onLogout() {
// stop stamina calculation
getStaminaManager().stopSustainedStaminaHandler();
// force to leave the dungeon // force to leave the dungeon
if(getScene().getSceneType() == SceneType.SCENE_DUNGEON){ if (getScene().getSceneType() == SceneType.SCENE_DUNGEON) {
this.getServer().getDungeonManager().exitDungeon(this); this.getServer().getDungeonManager().exitDungeon(this);
} }
// Leave world // Leave world
...@@ -1172,7 +1211,7 @@ public class Player { ...@@ -1172,7 +1211,7 @@ public class Player {
} else if (prop == PlayerProperty.PROP_LAST_CHANGE_AVATAR_TIME) { // 10001 } else if (prop == PlayerProperty.PROP_LAST_CHANGE_AVATAR_TIME) { // 10001
// TODO: implement sanity check // TODO: implement sanity check
} else if (prop == PlayerProperty.PROP_MAX_SPRING_VOLUME) { // 10002 } else if (prop == PlayerProperty.PROP_MAX_SPRING_VOLUME) { // 10002
if (!(value >= 0 && value <= GlobalMaximumSpringVolume)) { return false; } if (!(value >= 0 && value <= getSotSManager().GlobalMaximumSpringVolume)) { return false; }
} else if (prop == PlayerProperty.PROP_CUR_SPRING_VOLUME) { // 10003 } else if (prop == PlayerProperty.PROP_CUR_SPRING_VOLUME) { // 10003
int playerMaximumSpringVolume = getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME); int playerMaximumSpringVolume = getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME);
if (!(value >= 0 && value <= playerMaximumSpringVolume)) { return false; } if (!(value >= 0 && value <= playerMaximumSpringVolume)) { return false; }
...@@ -1189,7 +1228,7 @@ public class Player { ...@@ -1189,7 +1228,7 @@ public class Player {
} else if (prop == PlayerProperty.PROP_IS_TRANSFERABLE) { // 10009 } else if (prop == PlayerProperty.PROP_IS_TRANSFERABLE) { // 10009
if (!(0 <= value && value <= 1)) { return false; } if (!(0 <= value && value <= 1)) { return false; }
} else if (prop == PlayerProperty.PROP_MAX_STAMINA) { // 10010 } else if (prop == PlayerProperty.PROP_MAX_STAMINA) { // 10010
if (!(value >= 0 && value <= GlobalMaximumStamina)) { return false; } if (!(value >= 0 && value <= getStaminaManager().GlobalMaximumStamina)) { return false; }
} else if (prop == PlayerProperty.PROP_CUR_PERSIST_STAMINA) { // 10011 } else if (prop == PlayerProperty.PROP_CUR_PERSIST_STAMINA) { // 10011
int playerMaximumStamina = getProperty(PlayerProperty.PROP_MAX_STAMINA); int playerMaximumStamina = getProperty(PlayerProperty.PROP_MAX_STAMINA);
if (!(value >= 0 && value <= playerMaximumStamina)) { return false; } if (!(value >= 0 && value <= playerMaximumStamina)) { return false; }
...@@ -1200,7 +1239,7 @@ public class Player { ...@@ -1200,7 +1239,7 @@ public class Player {
} else if (prop == PlayerProperty.PROP_PLAYER_EXP) { // 10014 } else if (prop == PlayerProperty.PROP_PLAYER_EXP) { // 10014
if (!(0 <= value)) { return false; } if (!(0 <= value)) { return false; }
} else if (prop == PlayerProperty.PROP_PLAYER_HCOIN) { // 10015 } else if (prop == PlayerProperty.PROP_PLAYER_HCOIN) { // 10015
// see 10015 // see PlayerProperty.PROP_PLAYER_HCOIN comments
} else if (prop == PlayerProperty.PROP_PLAYER_SCOIN) { // 10016 } else if (prop == PlayerProperty.PROP_PLAYER_SCOIN) { // 10016
// See 10015 // See 10015
} else if (prop == PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE) { // 10017 } else if (prop == PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE) { // 10017
......
...@@ -557,7 +557,7 @@ public class TeamManager { ...@@ -557,7 +557,7 @@ public class TeamManager {
// return; // return;
// } // }
// } // }
player.getMovementManager().resetTimer(); // prevent drowning immediately after respawn player.getStaminaManager().stopSustainedStaminaHandler(); // prevent drowning immediately after respawn
// Revive all team members // Revive all team members
for (EntityAvatar entity : getActiveTeam()) { for (EntityAvatar entity : getActiveTeam()) {
......
...@@ -106,6 +106,12 @@ public class Scene { ...@@ -106,6 +106,12 @@ public class Scene {
return this.entities.get(id); return this.entities.get(id);
} }
public GameEntity getEntityByConfigId(int configId) {
return this.entities.values().stream()
.filter(x -> x.getConfigId() == configId)
.findFirst()
.orElse(null);
}
/** /**
* @return the autoCloseTime * @return the autoCloseTime
*/ */
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment