Support Open Chest

This commit is contained in:
Akka
2022-05-18 15:13:31 +08:00
committed by Melledy
parent df580bf519
commit 5f13a51668
14 changed files with 380 additions and 62 deletions

View File

@@ -1,18 +1,16 @@
package emu.grasscutter.game.entity;
import java.util.Arrays;
import java.util.List;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.GadgetData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.ClientGadgetInfoOuterClass;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.BossChestInfoOuterClass;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
@@ -27,11 +25,14 @@ import emu.grasscutter.net.proto.WorktopInfoOuterClass.WorktopInfo;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import lombok.ToString;
import java.util.Arrays;
import java.util.Random;
@ToString(callSuper = true)
public class EntityGadget extends EntityBaseGadget {
private final GadgetData data;
private final Position pos;
@@ -154,4 +155,30 @@ public class EntityGadget extends EntityBaseGadget {
return entityInfo.build();
}
public void openChest(Player player) {
var chestRewardMap = getScene().getWorld().getServer().getWorldDataManager().getChestRewardMap();
var chestReward = chestRewardMap.get(this.getGadgetData().getJsonName());
if(chestReward == null){
Grasscutter.getLogger().warn("Could not found the config of this type of Chests {}", this.getGadgetData().getJsonName());
return;
}
player.earnExp(chestReward.getAdvExp());
player.getInventory().addItem(201, chestReward.getResin());
var mora = chestReward.getMora() * (1 + (player.getWorldLevel() - 1) * 0.5);
player.getInventory().addItem(202, (int)mora);
for(int i=0;i<chestReward.getContent().size();i++){
getScene().addItemEntity(chestReward.getContent().get(i).getItemId(), chestReward.getContent().get(i).getCount(), this);
}
var random = new Random(System.currentTimeMillis());
for(int i=0;i<chestReward.getRandomCount();i++){
var index = random.nextInt(chestReward.getRandomContent().size());
var item = chestReward.getRandomContent().get(index);
getScene().addItemEntity(item.getItemId(), item.getCount(), this);
}
}
}

View File

@@ -4,12 +4,10 @@ import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.PropGrowCurve;
import emu.grasscutter.data.def.MonsterCurveData;
import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.game.dungeons.DungeonChallenge;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World;
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
@@ -24,6 +22,7 @@ import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
import emu.grasscutter.net.proto.SceneMonsterInfoOuterClass.SceneMonsterInfo;
import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.utils.Position;
import emu.grasscutter.utils.ProtoHelper;
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
@@ -126,7 +125,9 @@ public class EntityMonster extends GameEntity {
}
// prevent spawn monster after success
if(getScene().getChallenge() != null && getScene().getChallenge().inProgress()){
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, null);
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, new ScriptArgs().setParam1(this.getConfigId()));
}else if(getScene().getChallenge() == null){
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, new ScriptArgs().setParam1(this.getConfigId()));
}
}
}

View File

@@ -47,6 +47,7 @@ import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.scripts.constants.ScriptGadgetState;
import emu.grasscutter.server.event.player.PlayerJoinEvent;
import emu.grasscutter.server.event.player.PlayerQuitEvent;
import emu.grasscutter.server.game.GameServer;
@@ -927,6 +928,13 @@ public class Player {
this.sendPacket(new PacketGadgetInteractRsp(gadget, InteractType.INTERACT_OPEN_STATUE));
}
else if (gadget.getGadgetData().getType() == EntityType.Chest) {
getScene().updateGadgetState(gadget, ScriptGadgetState.ChestOpened);
gadget.openChest(this);
this.sendPacket(new PacketGadgetInteractRsp(gadget, InteractType.INTERACT_OPEN_CHEST));
getScene().killEntity(gadget, 0);
}
} else {
// Delete directly
entity.getScene().removeEntity(entity);

View File

@@ -0,0 +1,22 @@
package emu.grasscutter.game.world;
import emu.grasscutter.game.inventory.ItemDef;
import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;
import java.util.List;
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ChestReward {
List<String> objNames;
int advExp;
int resin;
int mora;
int sigil;
List<ItemDef> content;
int randomCount;
List<ItemDef> randomContent;
}

View File

@@ -3,10 +3,7 @@ package emu.grasscutter.game.world;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameDepot;
import emu.grasscutter.data.def.DungeonData;
import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.data.def.SceneData;
import emu.grasscutter.data.def.WorldLevelData;
import emu.grasscutter.data.def.*;
import emu.grasscutter.game.dungeons.DungeonChallenge;
import emu.grasscutter.game.dungeons.DungeonSettleListener;
import emu.grasscutter.game.entity.*;
@@ -24,11 +21,8 @@ import emu.grasscutter.scripts.SceneIndexManager;
import emu.grasscutter.scripts.SceneScriptManager;
import emu.grasscutter.scripts.data.SceneBlock;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.server.packet.send.PacketAvatarSkillInfoNotify;
import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify;
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
import emu.grasscutter.server.packet.send.PacketSceneEntityDisappearNotify;
import emu.grasscutter.server.packet.send.*;
import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -37,6 +31,8 @@ import org.danilopianini.util.SpatialIndex;
import java.util.*;
import java.util.stream.Collectors;
import static emu.grasscutter.utils.Language.translate;
public class Scene {
private final World world;
private final SceneData sceneData;
@@ -586,8 +582,10 @@ public class Scene {
do {
var suiteData = group.getSuiteByIndex(suite);
suiteData.sceneTriggers.forEach(getScriptManager()::registerTrigger);
entities.addAll(suiteData.sceneGadgets.stream()
.map(g -> scriptManager.createGadgets(group.id, group.block_id, g)).toList());
.map(g -> scriptManager.createGadget(group.id, group.block_id, g)).toList());
entities.addAll(suiteData.sceneMonsters.stream()
.map(mob -> scriptManager.createMonster(group.id, group.block_id, mob)).toList());
suite++;
@@ -609,7 +607,7 @@ public class Scene {
for (SceneGroup group : block.groups) {
if(group.triggers != null){
group.triggers.forEach(getScriptManager()::deregisterTrigger);
group.triggers.values().forEach(getScriptManager()::deregisterTrigger);
}
if(group.regions != null){
group.regions.forEach(getScriptManager()::deregisterRegion);
@@ -681,4 +679,27 @@ public class Scene {
player.getSession().send(packet);
}
}
public void addItemEntity(int itemId, int amount, GameEntity bornForm){
ItemData itemData = GameData.getItemDataMap().get(itemId);
if (itemData == null) {
return;
}
if (itemData.isEquip()) {
float range = (3f + (.1f * amount));
for (int i = 0; i < amount; i++) {
Position pos = bornForm.getPosition().clone().addX((float) (Math.random() * range) - (range / 2)).addZ((float) (Math.random() * range) - (range / 2)).addZ(.9f);
EntityItem entity = new EntityItem(this, null, itemData, pos, 1);
addEntity(entity);
}
} else {
EntityItem entity = new EntityItem(this, null, itemData, bornForm.getPosition().clone().addZ(.9f), amount);
addEntity(entity);
}
}
public void updateGadgetState(EntityGadget gadget, int state){
gadget.setState(state);
broadcastPacket(new PacketGadgetStateNotify(gadget, state));
}
}

View File

@@ -0,0 +1,41 @@
package emu.grasscutter.game.world;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.server.game.GameServer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static emu.grasscutter.Configuration.DATA;
public class WorldDataManager {
private final GameServer gameServer;
private final Map<String, ChestReward> chestRewardMap;
public WorldDataManager(GameServer gameServer){
this.gameServer = gameServer;
this.chestRewardMap = new HashMap<>();
load();
}
public synchronized void load(){
try {
List<ChestReward> chestReward = Grasscutter.getGsonFactory().fromJson(
Files.readString(Path.of(DATA("ChestReward.json"))),
TypeToken.getParameterized(List.class, ChestReward.class).getType());
chestReward.forEach(reward ->
reward.getObjNames().forEach(name -> chestRewardMap.put(name, reward)));
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load chest reward config.", e);
}
}
public Map<String, ChestReward> getChestRewardMap() {
return chestRewardMap;
}
}