mirror of
https://github.com/Melledy/LunarCore.git
synced 2026-03-23 07:22:25 +01:00
Added group state handler and improved interaction handling
This commit is contained in:
@@ -33,6 +33,7 @@ public class GameData {
|
||||
@Getter private static Int2ObjectMap<HeroExcel> heroExcelMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static Int2ObjectMap<ShopExcel> shopExcelMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static Int2ObjectMap<RewardExcel> rewardExcelMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static Int2ObjectMap<InteractExcel> interactExcelMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static Int2ObjectMap<PlayerIconExcel> playerIconExcelMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static Int2ObjectMap<ItemComposeExcel> itemComposeExcelMap = new Int2ObjectOpenHashMap<>();
|
||||
@Getter private static Int2ObjectMap<ActivityPanelExcel> activityPanelExcelMap = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
@@ -72,10 +72,12 @@ public class FloorInfo {
|
||||
// Hacky way to setup prop triggers
|
||||
if (json.contains("Maze_GroupProp_OpenTreasure_WhenMonsterDie")) {
|
||||
prop.setTrigger(new TriggerOpenTreasureWhenMonsterDie(group.getId()));
|
||||
} else if (json.contains("Maze_Chap02_X201_Event_PuzzleCompass_WayPoint_Controller_01")) {
|
||||
prop.setTrigger(new TriggerPuzzleCompassWayPointController(prop.getSharedValueByKey("PuzzleCompass_Prop"), prop.getSharedValueByKey("PuzzleChest_Prop")));
|
||||
} else if (json.contains("Maze_Chap02_X201_Event_PuzzleCompass_WayPoint_Controller")) {
|
||||
prop.setTrigger(new TriggerPuzzleCompassWayPointController(group.getId()));
|
||||
}
|
||||
|
||||
// Clear for garbage collection
|
||||
prop.setValueSource(null);
|
||||
prop.setInitLevelGraph(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ public class PropInfo extends ObjectInfo {
|
||||
private int CocoonID;
|
||||
private int FarmElementID;
|
||||
private boolean IsClientOnly;
|
||||
private PropValueSource ValueSource;
|
||||
|
||||
@Setter private PropValueSource ValueSource;
|
||||
@Setter private String InitLevelGraph;
|
||||
@Setter private PropState State = PropState.Closed;
|
||||
|
||||
|
||||
27
src/main/java/emu/lunarcore/data/excel/InteractExcel.java
Normal file
27
src/main/java/emu/lunarcore/data/excel/InteractExcel.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package emu.lunarcore.data.excel;
|
||||
|
||||
import emu.lunarcore.data.GameResource;
|
||||
import emu.lunarcore.data.ResourceType;
|
||||
import emu.lunarcore.game.enums.PropState;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ResourceType(name = {"InteractConfig.json"})
|
||||
public class InteractExcel extends GameResource {
|
||||
private int InteractID;
|
||||
private PropState SrcState;
|
||||
private PropState TargetState = PropState.Closed;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return InteractID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Just in case we forget to update the prop state enum
|
||||
if (this.TargetState == null) {
|
||||
this.TargetState = PropState.Closed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
package emu.lunarcore.data.excel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import emu.lunarcore.data.GameResource;
|
||||
import emu.lunarcore.data.ResourceType;
|
||||
import emu.lunarcore.game.enums.PropState;
|
||||
import emu.lunarcore.game.enums.PropType;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -12,6 +15,7 @@ public class PropExcel extends GameResource {
|
||||
private long PropName;
|
||||
private String JsonPath;
|
||||
private PropType PropType;
|
||||
private Set<PropState> PropStateList;
|
||||
|
||||
private transient boolean recoverHp;
|
||||
private transient boolean recoverMp;
|
||||
@@ -34,6 +38,11 @@ public class PropExcel extends GameResource {
|
||||
this.isDoor = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity
|
||||
if (this.PropStateList == null) {
|
||||
this.PropStateList = Set.of();
|
||||
}
|
||||
|
||||
// Clear for optimization
|
||||
this.JsonPath = null;
|
||||
|
||||
@@ -12,6 +12,7 @@ import emu.lunarcore.data.GameData;
|
||||
import emu.lunarcore.data.config.AnchorInfo;
|
||||
import emu.lunarcore.data.config.FloorInfo;
|
||||
import emu.lunarcore.data.config.PropInfo;
|
||||
import emu.lunarcore.data.excel.InteractExcel;
|
||||
import emu.lunarcore.data.excel.ItemUseExcel;
|
||||
import emu.lunarcore.data.excel.MapEntranceExcel;
|
||||
import emu.lunarcore.data.excel.MazePlaneExcel;
|
||||
@@ -578,7 +579,7 @@ public class Player implements Tickable {
|
||||
return true;
|
||||
}
|
||||
|
||||
public EntityProp interactWithProp(int propEntityId) {
|
||||
public EntityProp interactWithProp(int interactId, int propEntityId) {
|
||||
// Sanity
|
||||
if (this.getScene() == null) return null;
|
||||
|
||||
@@ -592,33 +593,44 @@ public class Player implements Tickable {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Handle prop interaction action
|
||||
// Get interact handler
|
||||
InteractExcel interactExcel = GameData.getInteractExcelMap().get(interactId);
|
||||
if (interactExcel == null) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
// Validate
|
||||
if (interactExcel.getSrcState() != null && prop.getState() != interactExcel.getSrcState()) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
// Save old state
|
||||
PropState oldState = prop.getState();
|
||||
|
||||
// Set group and prop state
|
||||
this.sendPacket(new PacketGroupStateChangeScNotify(getEntryId(), prop.getGroupId(), interactExcel.getTargetState()));
|
||||
prop.setState(interactExcel.getTargetState());
|
||||
|
||||
// Handle any extra interaction actions
|
||||
switch (prop.getExcel().getPropType()) {
|
||||
case PROP_TREASURE_CHEST -> {
|
||||
if (prop.getState() == PropState.ChestClosed) {
|
||||
// Open chest
|
||||
prop.setState(PropState.ChestUsed);
|
||||
if (oldState == PropState.ChestClosed && prop.getState() == PropState.ChestUsed) {
|
||||
// Handle drops
|
||||
var drops = this.getServer().getDropService().calculateDropsFromProp(prop.getPropId());
|
||||
this.getInventory().addItems(drops, true);
|
||||
// Done
|
||||
return prop;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
case PROP_MAZE_PUZZLE -> {
|
||||
// Finish puzzle
|
||||
prop.setState(PropState.Locked);
|
||||
// Trigger event
|
||||
this.getScene().invokePropTrigger(PropTriggerType.PUZZLE_FINISH, prop.getGroupId(), prop.getInstId());
|
||||
//
|
||||
return prop;
|
||||
}
|
||||
default -> {
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Return prop when we are done
|
||||
return prop;
|
||||
}
|
||||
|
||||
public void onMove() {
|
||||
|
||||
@@ -155,6 +155,14 @@ public class Scene implements Tickable {
|
||||
public synchronized GameEntity getEntityById(int id) {
|
||||
return this.getEntities().get(id);
|
||||
}
|
||||
|
||||
public synchronized <T extends GameEntity> List<T> getEntitiesByGroup(Class<T> entityType, int groupId) {
|
||||
return this.getEntities().values()
|
||||
.stream()
|
||||
.filter(e -> entityType.isInstance(e) && e.getGroupId() == groupId)
|
||||
.map(entityType::cast)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public void syncLineup() {
|
||||
// Get current lineup
|
||||
|
||||
@@ -54,17 +54,30 @@ public class EntityProp implements GameEntity {
|
||||
return excel.getId();
|
||||
}
|
||||
|
||||
public void setState(PropState state) {
|
||||
this.setState(state, this.getScene().isLoaded());
|
||||
public boolean setState(PropState state) {
|
||||
return this.setState(state, this.getScene().isLoaded());
|
||||
}
|
||||
|
||||
public void setState(PropState state, boolean sendPacket) {
|
||||
public boolean setState(PropState state, boolean sendPacket) {
|
||||
// Only set state if its been changed
|
||||
PropState oldState = this.getState();
|
||||
if (oldState == state) return false;
|
||||
|
||||
// Sanity check
|
||||
if (!this.getExcel().getPropStateList().contains(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set state
|
||||
this.state = state;
|
||||
|
||||
// Sync state update to client
|
||||
if (sendPacket) {
|
||||
this.getScene().getPlayer().sendPacket(new PacketSceneGroupRefreshScNotify(this, null));
|
||||
}
|
||||
|
||||
// Success
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,6 +111,10 @@ public class EntityProp implements GameEntity {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Prop: " + this.getEntityId() + ", Group: " + this.groupId + ", Inst: " + this.getInstId();
|
||||
return "[Prop] EntityId: " + this.getEntityId() +
|
||||
", PropId: " + this.getExcel().getId() +
|
||||
" (" + this.getExcel().getPropType() + ")" +
|
||||
", Group: " + this.groupId +
|
||||
", ConfigId: " + this.getInstId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import emu.lunarcore.game.enums.PropState;
|
||||
import emu.lunarcore.game.enums.PropType;
|
||||
import emu.lunarcore.game.scene.Scene;
|
||||
import emu.lunarcore.game.scene.entity.EntityProp;
|
||||
import emu.lunarcore.game.scene.entity.GameEntity;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@@ -27,17 +26,10 @@ public class TriggerOpenTreasureWhenMonsterDie extends PropTrigger {
|
||||
|
||||
@Override
|
||||
public void run(Scene scene) {
|
||||
synchronized (scene) {
|
||||
for (GameEntity entity : scene.getEntities().values()) {
|
||||
if (entity.getGroupId() != this.groupId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity instanceof EntityProp prop) {
|
||||
if (prop.getExcel().getPropType() == PropType.PROP_TREASURE_CHEST) {
|
||||
prop.setState(PropState.ChestClosed);
|
||||
}
|
||||
}
|
||||
// Open trigger
|
||||
for (var prop : scene.getEntitiesByGroup(EntityProp.class, this.getGroupId())) {
|
||||
if (prop.getExcel().getPropType() == PropType.PROP_TREASURE_CHEST) {
|
||||
prop.setState(PropState.ChestClosed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,14 @@ package emu.lunarcore.game.scene.triggers;
|
||||
import emu.lunarcore.game.enums.PropState;
|
||||
import emu.lunarcore.game.scene.Scene;
|
||||
import emu.lunarcore.game.scene.entity.EntityProp;
|
||||
import emu.lunarcore.game.scene.entity.GameEntity;
|
||||
import emu.lunarcore.util.Utils;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class TriggerPuzzleCompassWayPointController extends PropTrigger {
|
||||
private int groupId;
|
||||
private int puzzleInstId;
|
||||
private int chestInstId;
|
||||
|
||||
public TriggerPuzzleCompassWayPointController(String compassKey, String chestKey) {
|
||||
String[] compass = compassKey.split(",");
|
||||
String[] chest = chestKey.split(",");
|
||||
|
||||
this.groupId = Utils.parseSafeInt(compass[0]);
|
||||
this.puzzleInstId = Utils.parseSafeInt(compass[1]);
|
||||
this.chestInstId = Utils.parseSafeInt(chest[1]);
|
||||
public TriggerPuzzleCompassWayPointController(int groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -29,23 +20,13 @@ public class TriggerPuzzleCompassWayPointController extends PropTrigger {
|
||||
|
||||
@Override
|
||||
public boolean shouldRun(int groupId, int instId) {
|
||||
return this.groupId == groupId && this.puzzleInstId == instId;
|
||||
return this.groupId == groupId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Scene scene) {
|
||||
synchronized (scene) {
|
||||
for (GameEntity entity : scene.getEntities().values()) {
|
||||
if (entity.getGroupId() != this.groupId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity instanceof EntityProp prop) {
|
||||
if (prop.getInstId() == chestInstId) {
|
||||
prop.setState(PropState.ChestClosed);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var prop : scene.getEntitiesByGroup(EntityProp.class, groupId)) {
|
||||
prop.setState(PropState.Open);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package emu.lunarcore.server.packet.recv;
|
||||
|
||||
import emu.lunarcore.proto.GroupStateChangeCsReqOuterClass.GroupStateChangeCsReq;
|
||||
import emu.lunarcore.server.game.GameSession;
|
||||
import emu.lunarcore.server.packet.CmdId;
|
||||
import emu.lunarcore.server.packet.Opcodes;
|
||||
import emu.lunarcore.server.packet.PacketHandler;
|
||||
import emu.lunarcore.server.packet.send.PacketGroupStateChangeScNotify;
|
||||
import emu.lunarcore.server.packet.send.PacketGroupStateChangeScRsp;
|
||||
|
||||
@Opcodes(CmdId.GroupStateChangeCsReq)
|
||||
public class HandlerGroupStateChangeCsReq extends PacketHandler {
|
||||
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] data) throws Exception {
|
||||
var req = GroupStateChangeCsReq.parseFrom(data);
|
||||
var groupInfo = req.getMutableGroupInfo();
|
||||
|
||||
session.send(new PacketGroupStateChangeScNotify(groupInfo));
|
||||
session.send(new PacketGroupStateChangeScRsp(groupInfo));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public class HandlerInteractPropCsReq extends PacketHandler {
|
||||
public void handle(GameSession session, byte[] data) throws Exception {
|
||||
var req = InteractPropCsReq.parseFrom(data);
|
||||
|
||||
EntityProp prop = session.getPlayer().interactWithProp(req.getPropEntityId());
|
||||
EntityProp prop = session.getPlayer().interactWithProp(req.getInteractId(), req.getPropEntityId());
|
||||
|
||||
session.send(new PacketInteractPropScRsp(prop));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package emu.lunarcore.server.packet.send;
|
||||
|
||||
import emu.lunarcore.game.enums.PropState;
|
||||
import emu.lunarcore.proto.GroupStateChangeScNotifyOuterClass.GroupStateChangeScNotify;
|
||||
import emu.lunarcore.proto.GroupStateInfoOuterClass.GroupStateInfo;
|
||||
import emu.lunarcore.server.packet.BasePacket;
|
||||
import emu.lunarcore.server.packet.CmdId;
|
||||
|
||||
public class PacketGroupStateChangeScNotify extends BasePacket {
|
||||
|
||||
public PacketGroupStateChangeScNotify(GroupStateInfo groupInfo) {
|
||||
super(CmdId.GroupStateChangeScNotify);
|
||||
|
||||
var data = GroupStateChangeScNotify.newInstance();
|
||||
data.setGroupInfo(groupInfo);
|
||||
|
||||
this.setData(data);
|
||||
}
|
||||
|
||||
public PacketGroupStateChangeScNotify(int entryId, int groupId, PropState state) {
|
||||
super(CmdId.GroupStateChangeScNotify);
|
||||
|
||||
var data = GroupStateChangeScNotify.newInstance();
|
||||
|
||||
data.getMutableGroupInfo()
|
||||
.setEntryId(entryId)
|
||||
.setGroupId(groupId)
|
||||
.setGroupState(state.getVal());
|
||||
|
||||
this.setData(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package emu.lunarcore.server.packet.send;
|
||||
|
||||
import emu.lunarcore.proto.GroupStateChangeScNotifyOuterClass.GroupStateChangeScNotify;
|
||||
import emu.lunarcore.proto.GroupStateInfoOuterClass.GroupStateInfo;
|
||||
import emu.lunarcore.server.packet.BasePacket;
|
||||
import emu.lunarcore.server.packet.CmdId;
|
||||
|
||||
public class PacketGroupStateChangeScRsp extends BasePacket {
|
||||
|
||||
public PacketGroupStateChangeScRsp(GroupStateInfo groupInfo) {
|
||||
super(CmdId.GroupStateChangeScRsp);
|
||||
|
||||
var data = GroupStateChangeScNotify.newInstance();
|
||||
data.setGroupInfo(groupInfo);
|
||||
|
||||
this.setData(data);
|
||||
}
|
||||
}
|
||||
@@ -35,12 +35,16 @@ public class PacketSceneGroupRefreshScNotify extends BasePacket {
|
||||
|
||||
var group = SceneGroupRefreshInfo.newInstance();
|
||||
|
||||
for (var entity : toAdd) {
|
||||
group.addRefreshEntity(SceneEntityRefreshInfo.newInstance().setAddEntity(entity.toSceneEntityProto()));
|
||||
if (toAdd != null) {
|
||||
for (var entity : toAdd) {
|
||||
group.addRefreshEntity(SceneEntityRefreshInfo.newInstance().setAddEntity(entity.toSceneEntityProto()));
|
||||
}
|
||||
}
|
||||
|
||||
for (var entity : toRemove) {
|
||||
group.addRefreshEntity(SceneEntityRefreshInfo.newInstance().setDelEntity(entity.getEntityId()));
|
||||
|
||||
if (toRemove != null) {
|
||||
for (var entity : toRemove) {
|
||||
group.addRefreshEntity(SceneEntityRefreshInfo.newInstance().setDelEntity(entity.getEntityId()));
|
||||
}
|
||||
}
|
||||
|
||||
var data = SceneGroupRefreshScNotify.newInstance()
|
||||
|
||||
Reference in New Issue
Block a user