mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-01-25 12:52:57 +08:00
Big World Resources Collection Implement (#1368)
* init * init * init * revoke * fix error * mining support * mining support * Roks endurance support * Roks endurance support * Timed refresh * upgrade resource data * Timed refresh support * remove null gadget * Coordination * full synchronized * oh no, my math teacher will hit me! * synchronized onInteract * remove break; * supply re-spawn time , thanks to @wl23333 * Clean up and integrate collection spawns into SpawnDataEntries Co-authored-by: Melledy <52122272+Melledy@users.noreply.github.com>
This commit is contained in:
parent
17fb19ebc9
commit
2462da2ede
@ -1,6 +1,7 @@
|
|||||||
package emu.grasscutter.data;
|
package emu.grasscutter.data;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -27,6 +28,7 @@ import emu.grasscutter.data.common.PointData;
|
|||||||
import emu.grasscutter.data.common.ScenePointConfig;
|
import emu.grasscutter.data.common.ScenePointConfig;
|
||||||
import emu.grasscutter.game.world.SpawnDataEntry.*;
|
import emu.grasscutter.game.world.SpawnDataEntry.*;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
|
||||||
import static emu.grasscutter.Configuration.*;
|
import static emu.grasscutter.Configuration.*;
|
||||||
import static emu.grasscutter.utils.Language.translate;
|
import static emu.grasscutter.utils.Language.translate;
|
||||||
@ -306,19 +308,32 @@ public class ResourceLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void loadSpawnData() {
|
private static void loadSpawnData() {
|
||||||
List<SpawnGroupEntry> spawnEntryList = null;
|
String[] spawnDataNames = {"Spawns.json", "GadgetSpawns.json"};
|
||||||
|
Int2ObjectMap<SpawnGroupEntry> spawnEntryMap = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
// Read from cached file if exists
|
for (String name : spawnDataNames) {
|
||||||
try(InputStream spawnDataEntries = DataLoader.load("Spawns.json")) {
|
// Load spawn entries from file
|
||||||
spawnEntryList = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(spawnDataEntries), TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType());
|
try (InputStream spawnDataEntries = DataLoader.load(name)) {
|
||||||
} catch (Exception ignored) {}
|
Type type = TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType();
|
||||||
|
List<SpawnGroupEntry> list = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(spawnDataEntries), type);
|
||||||
if (spawnEntryList == null || spawnEntryList.isEmpty()) {
|
|
||||||
|
// Add spawns to group if it already exists in our spawn group map
|
||||||
|
for (SpawnGroupEntry group : list) {
|
||||||
|
if (spawnEntryMap.containsKey(group.getGroupId())) {
|
||||||
|
spawnEntryMap.get(group.getGroupId()).getSpawns().addAll(group.getSpawns());
|
||||||
|
} else {
|
||||||
|
spawnEntryMap.put(group.getGroupId(), group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spawnEntryMap.isEmpty()) {
|
||||||
Grasscutter.getLogger().error("No spawn data loaded!");
|
Grasscutter.getLogger().error("No spawn data loaded!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SpawnGroupEntry entry : spawnEntryList) {
|
for (SpawnGroupEntry entry : spawnEntryMap.values()) {
|
||||||
entry.getSpawns().forEach(s -> s.setGroup(entry));
|
entry.getSpawns().forEach(s -> s.setGroup(entry));
|
||||||
GameDepot.getSpawnListById(entry.getSceneId()).insert(entry, entry.getPos().getX(), entry.getPos().getZ());
|
GameDepot.getSpawnListById(entry.getSceneId()).insert(entry, entry.getPos().getX(), entry.getPos().getZ());
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,11 @@ import emu.grasscutter.data.excels.ItemData;
|
|||||||
import emu.grasscutter.game.avatar.Avatar;
|
import emu.grasscutter.game.avatar.Avatar;
|
||||||
import emu.grasscutter.game.entity.EntityAvatar;
|
import emu.grasscutter.game.entity.EntityAvatar;
|
||||||
import emu.grasscutter.game.entity.EntityClientGadget;
|
import emu.grasscutter.game.entity.EntityClientGadget;
|
||||||
|
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.entity.gadget.GadgetGatherObject;
|
||||||
|
import emu.grasscutter.game.entity.gadget.GadgetGatherPoint;
|
||||||
import emu.grasscutter.game.player.Player;
|
import emu.grasscutter.game.player.Player;
|
||||||
import emu.grasscutter.game.props.ElementType;
|
import emu.grasscutter.game.props.ElementType;
|
||||||
import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall;
|
import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall;
|
||||||
@ -98,26 +101,36 @@ public class AbilityManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception {
|
private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception {
|
||||||
|
// Sanity checks
|
||||||
GameEntity target = player.getScene().getEntityById(invoke.getEntityId());
|
GameEntity target = player.getScene().getEntityById(invoke.getEntityId());
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbilityInvokeEntryHead head = invoke.getHead();
|
|
||||||
if (head == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData());
|
AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData());
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroying rocks
|
||||||
|
if (target instanceof EntityGadget targetGadget && targetGadget.getContent() instanceof GadgetGatherObject gatherObject) {
|
||||||
|
if (data.getAction() == ModifierAction.REMOVED) {
|
||||||
|
gatherObject.dropItems(this.getPlayer());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity checks
|
||||||
|
AbilityInvokeEntryHead head = invoke.getHead();
|
||||||
|
if (head == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GameEntity sourceEntity = player.getScene().getEntityById(data.getApplyEntityId());
|
GameEntity sourceEntity = player.getScene().getEntityById(data.getApplyEntityId());
|
||||||
if (sourceEntity == null) {
|
if (sourceEntity == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is not how it works but we will keep it for now since healing abilities dont work properly anyways
|
// This is not how it works but we will keep it for now since healing abilities dont work properly anyways
|
||||||
if (data.getAction() == ModifierAction.ADDED && data.getParentAbilityName() != null) {
|
if (data.getAction() == ModifierAction.ADDED && data.getParentAbilityName() != null) {
|
||||||
// Handle add modifier here
|
// Handle add modifier here
|
||||||
@ -133,6 +146,7 @@ public class AbilityManager {
|
|||||||
// Add to meta modifier list
|
// Add to meta modifier list
|
||||||
target.getMetaModifiers().put(head.getInstancedModifierId(), modifierString);
|
target.getMetaModifiers().put(head.getInstancedModifierId(), modifierString);
|
||||||
} else if (data.getAction() == ModifierAction.REMOVED) {
|
} else if (data.getAction() == ModifierAction.REMOVED) {
|
||||||
|
// Handle remove modifier
|
||||||
String modifierString = target.getMetaModifiers().get(head.getInstancedModifierId());
|
String modifierString = target.getMetaModifiers().get(head.getInstancedModifierId());
|
||||||
|
|
||||||
if (modifierString != null) {
|
if (modifierString != null) {
|
||||||
|
@ -8,11 +8,13 @@ import emu.grasscutter.game.props.EntityType;
|
|||||||
import emu.grasscutter.game.props.LifeState;
|
import emu.grasscutter.game.props.LifeState;
|
||||||
import emu.grasscutter.game.props.PlayerProperty;
|
import emu.grasscutter.game.props.PlayerProperty;
|
||||||
import emu.grasscutter.game.world.Scene;
|
import emu.grasscutter.game.world.Scene;
|
||||||
|
import emu.grasscutter.game.world.SpawnDataEntry;
|
||||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||||
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
||||||
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
|
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
|
||||||
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
|
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
|
||||||
|
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
|
||||||
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
|
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
|
||||||
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
|
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
|
||||||
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
|
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
|
||||||
@ -27,6 +29,7 @@ import emu.grasscutter.server.packet.send.PacketGadgetStateNotify;
|
|||||||
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
|
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
|
||||||
import emu.grasscutter.utils.Position;
|
import emu.grasscutter.utils.Position;
|
||||||
import emu.grasscutter.utils.ProtoHelper;
|
import emu.grasscutter.utils.ProtoHelper;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
@ -40,19 +43,24 @@ public class EntityGadget extends EntityBaseGadget {
|
|||||||
private int state;
|
private int state;
|
||||||
private int pointType;
|
private int pointType;
|
||||||
private GadgetContent content;
|
private GadgetContent content;
|
||||||
|
private Int2FloatOpenHashMap fightProp;
|
||||||
private SceneGadget metaGadget;
|
private SceneGadget metaGadget;
|
||||||
|
|
||||||
public EntityGadget(Scene scene, int gadgetId, Position pos) {
|
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot) {
|
||||||
super(scene);
|
super(scene);
|
||||||
this.data = GameData.getGadgetDataMap().get(gadgetId);
|
this.data = GameData.getGadgetDataMap().get(gadgetId);
|
||||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||||
this.gadgetId = gadgetId;
|
this.gadgetId = gadgetId;
|
||||||
this.pos = pos.clone();
|
this.pos = pos.clone();
|
||||||
this.rot = new Position();
|
this.rot = rot != null ? rot.clone() : new Position();
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityGadget(Scene scene, int gadgetId, Position pos, GadgetContent content) {
|
public EntityGadget(Scene scene, int gadgetId, Position pos) {
|
||||||
this(scene, gadgetId, pos);
|
this(scene, gadgetId, pos, new Position());
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot, GadgetContent content) {
|
||||||
|
this(scene, gadgetId, pos, rot);
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +134,7 @@ public class EntityGadget extends EntityBaseGadget {
|
|||||||
EntityType type = getGadgetData().getType();
|
EntityType type = getGadgetData().getType();
|
||||||
GadgetContent content = switch (type) {
|
GadgetContent content = switch (type) {
|
||||||
case GatherPoint -> new GadgetGatherPoint(this);
|
case GatherPoint -> new GadgetGatherPoint(this);
|
||||||
|
case GatherObject -> new GadgetGatherObject(this);
|
||||||
case Worktop -> new GadgetWorktop(this);
|
case Worktop -> new GadgetWorktop(this);
|
||||||
case RewardStatue -> new GadgetRewardStatue(this);
|
case RewardStatue -> new GadgetRewardStatue(this);
|
||||||
case Chest -> new GadgetChest(this);
|
case Chest -> new GadgetChest(this);
|
||||||
@ -137,7 +146,8 @@ public class EntityGadget extends EntityBaseGadget {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Int2FloatOpenHashMap getFightProperties() {
|
public Int2FloatOpenHashMap getFightProperties() {
|
||||||
return null;
|
if (this.fightProp == null) this.fightProp = new Int2FloatOpenHashMap();
|
||||||
|
return this.fightProp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -148,7 +158,10 @@ public class EntityGadget extends EntityBaseGadget {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeath(int killerId) {
|
public void onDeath(int killerId) {
|
||||||
if(getScene().getChallenge() != null){
|
if (this.getSpawnEntry() != null) {
|
||||||
|
this.getScene().getDeadSpawnedEntities().add(getSpawnEntry());
|
||||||
|
}
|
||||||
|
if (getScene().getChallenge() != null) {
|
||||||
getScene().getChallenge().onGadgetDeath(this);
|
getScene().getChallenge().onGadgetDeath(this);
|
||||||
}
|
}
|
||||||
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_GADGET_DIE, new ScriptArgs(this.getConfigId()));
|
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_GADGET_DIE, new ScriptArgs(this.getConfigId()));
|
||||||
@ -178,6 +191,11 @@ public class EntityGadget extends EntityBaseGadget {
|
|||||||
.build();
|
.build();
|
||||||
entityInfo.addPropList(pair);
|
entityInfo.addPropList(pair);
|
||||||
|
|
||||||
|
// We do not use the getter to null check because the getter will create a fight prop map if it is null
|
||||||
|
if (this.fightProp != null) {
|
||||||
|
this.addAllFightPropsToEntityInfo(entityInfo);
|
||||||
|
}
|
||||||
|
|
||||||
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
|
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
|
||||||
.setGadgetId(this.getGadgetId())
|
.setGadgetId(this.getGadgetId())
|
||||||
.setGroupId(this.getGroupId())
|
.setGroupId(this.getGroupId())
|
||||||
|
@ -8,12 +8,14 @@ import emu.grasscutter.game.props.LifeState;
|
|||||||
import emu.grasscutter.game.world.Scene;
|
import emu.grasscutter.game.world.Scene;
|
||||||
import emu.grasscutter.game.world.SpawnDataEntry;
|
import emu.grasscutter.game.world.SpawnDataEntry;
|
||||||
import emu.grasscutter.game.world.World;
|
import emu.grasscutter.game.world.World;
|
||||||
|
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
|
||||||
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
|
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
|
||||||
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
|
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
|
||||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||||
import emu.grasscutter.utils.Position;
|
import emu.grasscutter.utils.Position;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||||
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;
|
||||||
@ -124,6 +126,16 @@ public abstract class GameEntity {
|
|||||||
return getFightProperties().getOrDefault(prop.getId(), 0f);
|
return getFightProperties().getOrDefault(prop.getId(), 0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addAllFightPropsToEntityInfo(SceneEntityInfo.Builder entityInfo) {
|
||||||
|
for (Int2FloatMap.Entry entry : getFightProperties().int2FloatEntrySet()) {
|
||||||
|
if (entry.getIntKey() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FightPropPair fightProp = FightPropPair.newBuilder().setPropType(entry.getIntKey()).setPropValue(entry.getFloatValue()).build();
|
||||||
|
entityInfo.addFightPropList(fightProp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getBlockId() {
|
public int getBlockId() {
|
||||||
return blockId;
|
return blockId;
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,12 @@ package emu.grasscutter.game.entity.gadget;
|
|||||||
|
|
||||||
import emu.grasscutter.game.entity.EntityGadget;
|
import emu.grasscutter.game.entity.EntityGadget;
|
||||||
import emu.grasscutter.game.player.Player;
|
import emu.grasscutter.game.player.Player;
|
||||||
import emu.grasscutter.net.proto.InterOpTypeOuterClass;
|
|
||||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||||
|
|
||||||
public abstract class GadgetContent {
|
public abstract class GadgetContent {
|
||||||
private final EntityGadget gadget;
|
private final EntityGadget gadget;
|
||||||
|
|
||||||
public GadgetContent(EntityGadget gadget) {
|
public GadgetContent(EntityGadget gadget) {
|
||||||
this.gadget = gadget;
|
this.gadget = gadget;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
package emu.grasscutter.game.entity.gadget;
|
||||||
|
|
||||||
|
import emu.grasscutter.data.GameData;
|
||||||
|
import emu.grasscutter.data.excels.ItemData;
|
||||||
|
import emu.grasscutter.game.entity.EntityGadget;
|
||||||
|
import emu.grasscutter.game.entity.EntityItem;
|
||||||
|
import emu.grasscutter.game.inventory.GameItem;
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
|
import emu.grasscutter.game.props.ActionReason;
|
||||||
|
import emu.grasscutter.game.world.Scene;
|
||||||
|
import emu.grasscutter.net.proto.GatherGadgetInfoOuterClass.GatherGadgetInfo;
|
||||||
|
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
|
||||||
|
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||||
|
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||||
|
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
|
||||||
|
import emu.grasscutter.utils.Position;
|
||||||
|
import emu.grasscutter.utils.Utils;
|
||||||
|
|
||||||
|
public class GadgetGatherObject extends GadgetContent {
|
||||||
|
private int itemId;
|
||||||
|
private boolean isForbidGuest;
|
||||||
|
|
||||||
|
public GadgetGatherObject(EntityGadget gadget) {
|
||||||
|
super(gadget);
|
||||||
|
|
||||||
|
if (gadget.getSpawnEntry() != null) {
|
||||||
|
this.itemId = gadget.getSpawnEntry().getGatherItemId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getItemId() {
|
||||||
|
return this.itemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isForbidGuest() {
|
||||||
|
return isForbidGuest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onInteract(Player player, GadgetInteractReq req) {
|
||||||
|
// Sanity check
|
||||||
|
ItemData itemData = GameData.getItemDataMap().get(getItemId());
|
||||||
|
if (itemData == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameItem item = new GameItem(itemData, 1);
|
||||||
|
player.getInventory().addItem(item, ActionReason.Gather);
|
||||||
|
|
||||||
|
getGadget().getScene().broadcastPacket(new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_GATHER));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {
|
||||||
|
GatherGadgetInfo gatherGadgetInfo = GatherGadgetInfo.newBuilder()
|
||||||
|
.setItemId(this.getItemId())
|
||||||
|
.setIsForbidGuest(this.isForbidGuest())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
gadgetInfo.setGatherGadget(gatherGadgetInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dropItems(Player player) {
|
||||||
|
Scene scene = getGadget().getScene();
|
||||||
|
int times = Utils.randomRange(1,2);
|
||||||
|
|
||||||
|
for (int i = 0 ; i < times ; i++) {
|
||||||
|
EntityItem item = new EntityItem(
|
||||||
|
scene,
|
||||||
|
player,
|
||||||
|
GameData.getItemDataMap().get(itemId),
|
||||||
|
new Position(
|
||||||
|
getGadget().getPosition().getX() + (float)Utils.randomRange(1,5) / 5,
|
||||||
|
getGadget().getPosition().getY() + 2f,
|
||||||
|
getGadget().getPosition().getZ() + (float)Utils.randomRange(1,5) / 5
|
||||||
|
),
|
||||||
|
1,
|
||||||
|
true);
|
||||||
|
|
||||||
|
scene.addEntity(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
scene.killEntity(this.getGadget(), player.getTeamManager().getCurrentAvatarEntity().getId());
|
||||||
|
// Todo: add record
|
||||||
|
}
|
||||||
|
}
|
@ -3,31 +3,43 @@ package emu.grasscutter.game.entity.gadget;
|
|||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
import emu.grasscutter.data.excels.GatherData;
|
import emu.grasscutter.data.excels.GatherData;
|
||||||
import emu.grasscutter.game.entity.EntityGadget;
|
import emu.grasscutter.game.entity.EntityGadget;
|
||||||
|
import emu.grasscutter.game.entity.EntityItem;
|
||||||
import emu.grasscutter.game.inventory.GameItem;
|
import emu.grasscutter.game.inventory.GameItem;
|
||||||
import emu.grasscutter.game.player.Player;
|
import emu.grasscutter.game.player.Player;
|
||||||
import emu.grasscutter.game.props.ActionReason;
|
import emu.grasscutter.game.props.ActionReason;
|
||||||
|
import emu.grasscutter.game.world.Scene;
|
||||||
import emu.grasscutter.net.proto.GatherGadgetInfoOuterClass.GatherGadgetInfo;
|
import emu.grasscutter.net.proto.GatherGadgetInfoOuterClass.GatherGadgetInfo;
|
||||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||||
|
import emu.grasscutter.utils.Position;
|
||||||
|
import emu.grasscutter.utils.Utils;
|
||||||
|
|
||||||
public class GadgetGatherPoint extends GadgetContent {
|
public class GadgetGatherPoint extends GadgetContent {
|
||||||
private GatherData gatherData;
|
private int itemId;
|
||||||
|
private boolean isForbidGuest;
|
||||||
|
|
||||||
public GadgetGatherPoint(EntityGadget gadget) {
|
public GadgetGatherPoint(EntityGadget gadget) {
|
||||||
super(gadget);
|
super(gadget);
|
||||||
this.gatherData = GameData.getGatherDataMap().get(gadget.getPointType());
|
|
||||||
}
|
if (gadget.getSpawnEntry() != null) {
|
||||||
|
this.itemId = gadget.getSpawnEntry().getGatherItemId();
|
||||||
public GatherData getGatherData() {
|
} else {
|
||||||
return gatherData;
|
GatherData gatherData = GameData.getGatherDataMap().get(gadget.getPointType());
|
||||||
|
this.itemId = gatherData.getItemId();
|
||||||
|
this.isForbidGuest = gatherData.isForbidGuest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getItemId() {
|
public int getItemId() {
|
||||||
return getGatherData().getItemId();
|
return this.itemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isForbidGuest() {
|
||||||
|
return isForbidGuest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onInteract(Player player, GadgetInteractReq req) {
|
public boolean onInteract(Player player, GadgetInteractReq req) {
|
||||||
GameItem item = new GameItem(gatherData.getItemId(), 1);
|
GameItem item = new GameItem(getItemId(), 1);
|
||||||
|
|
||||||
player.getInventory().addItem(item, ActionReason.Gather);
|
player.getInventory().addItem(item, ActionReason.Gather);
|
||||||
|
|
||||||
@ -37,9 +49,33 @@ public class GadgetGatherPoint extends GadgetContent {
|
|||||||
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {
|
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {
|
||||||
GatherGadgetInfo gatherGadgetInfo = GatherGadgetInfo.newBuilder()
|
GatherGadgetInfo gatherGadgetInfo = GatherGadgetInfo.newBuilder()
|
||||||
.setItemId(this.getItemId())
|
.setItemId(this.getItemId())
|
||||||
.setIsForbidGuest(this.getGatherData().isForbidGuest())
|
.setIsForbidGuest(this.isForbidGuest())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
gadgetInfo.setGatherGadget(gatherGadgetInfo);
|
gadgetInfo.setGatherGadget(gatherGadgetInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dropItems(Player player) {
|
||||||
|
Scene scene = getGadget().getScene();
|
||||||
|
int times = Utils.randomRange(1,2);
|
||||||
|
|
||||||
|
for (int i = 0 ; i < times ; i++) {
|
||||||
|
EntityItem item = new EntityItem(
|
||||||
|
scene,
|
||||||
|
player,
|
||||||
|
GameData.getItemDataMap().get(itemId),
|
||||||
|
new Position(
|
||||||
|
getGadget().getPosition().getX() + (float)Utils.randomRange(1,5) / 5,
|
||||||
|
getGadget().getPosition().getY() + 2f,
|
||||||
|
getGadget().getPosition().getZ() + (float)Utils.randomRange(1,5) / 5
|
||||||
|
),
|
||||||
|
1,
|
||||||
|
true);
|
||||||
|
|
||||||
|
scene.addEntity(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
scene.killEntity(this.getGadget(), player.getTeamManager().getCurrentAvatarEntity().getId());
|
||||||
|
// Todo: add record
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package emu.grasscutter.game.managers.collection;
|
||||||
|
|
||||||
|
|
||||||
|
import emu.grasscutter.game.props.FightProperty;
|
||||||
|
import emu.grasscutter.utils.Position;
|
||||||
|
|
||||||
|
public class CollectionData {
|
||||||
|
Gadget gadget;
|
||||||
|
MotionInfo motionInfo;
|
||||||
|
Prop[] fightPropList;
|
||||||
|
static class GatherGadget{
|
||||||
|
int itemId;
|
||||||
|
}
|
||||||
|
static class Gadget{
|
||||||
|
int gadgetId;
|
||||||
|
int authorityPeerId;
|
||||||
|
int configId;
|
||||||
|
int groupId;
|
||||||
|
boolean isEnableInteract;
|
||||||
|
GatherGadget gatherGadget;
|
||||||
|
}
|
||||||
|
static class MotionInfo{
|
||||||
|
Position pos;
|
||||||
|
Position rot;
|
||||||
|
}
|
||||||
|
static class Prop{
|
||||||
|
int propType;
|
||||||
|
float propValue;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package emu.grasscutter.game.managers.collection;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import emu.grasscutter.game.entity.EntityGadget;
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
|
|
||||||
|
public class CollectionManager {
|
||||||
|
private static final long SECOND = 1000; //1 Second
|
||||||
|
private static final long MINUTE = SECOND*60; //1 Minute
|
||||||
|
private static final long HOUR = MINUTE*60; //1 Hour
|
||||||
|
private static final long DAY = HOUR*24; //1 Day
|
||||||
|
private static final HashMap<Integer,Long> DEFINE_REFRESH_TIME = new HashMap<>();// <GadgetId,Waiting Millisecond>
|
||||||
|
private static final long DEFAULT_REFRESH_TIME = HOUR*6; // default 6 Hours
|
||||||
|
|
||||||
|
static {
|
||||||
|
DEFINE_REFRESH_TIME.put(70590027,3*DAY);//星银矿石 3 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70590036,3*DAY);//紫晶块 3 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70520003,3*DAY);//水晶 3 Days
|
||||||
|
|
||||||
|
DEFINE_REFRESH_TIME.put(70590013,2*DAY);//嘟嘟莲 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540029,2*DAY);//清心 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540028,2*DAY);//星螺 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540027,2*DAY);//马尾 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540026,2*DAY);//琉璃袋 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540022,2*DAY);//落落莓 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540020,2*DAY);//慕风蘑菇 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540019,2*DAY);//风车菊 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540018,2*DAY);//塞西莉亚花 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540015,2*DAY);//霓裳花 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540014,2*DAY);//莲蓬 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540013,2*DAY);//钩钩果 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540012,2*DAY);//琉璃百合 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70540008,2*DAY);//绝云椒椒 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70520018,2*DAY);//夜泊石 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70520002,2*DAY);//白铁矿 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70510012,2*DAY);//石珀 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70510009,2*DAY);//蒲公英 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70510007,2*DAY);//冰雾花 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70510006,2*DAY);//烈焰花 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70510005,2*DAY);//电气水晶 2 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70510004,2*DAY);//小灯草 2 Days
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_REFRESH_TIME.put(70540021,DAY);//日落果 1 Day
|
||||||
|
DEFINE_REFRESH_TIME.put(70540005,DAY);//松果 1 Day
|
||||||
|
DEFINE_REFRESH_TIME.put(70540003,DAY);//苹果 1 Day
|
||||||
|
DEFINE_REFRESH_TIME.put(70540001,DAY);//树莓 1 Day
|
||||||
|
DEFINE_REFRESH_TIME.put(70520019,DAY);//魔晶块 1 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70520008,DAY);//金鱼草 1 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70520007,DAY);//白萝卜 1 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70520006,DAY);//胡萝卜 1 Days
|
||||||
|
DEFINE_REFRESH_TIME.put(70520004,DAY);//蘑菇 1 Day
|
||||||
|
DEFINE_REFRESH_TIME.put(70520001,DAY);//铁矿 1 Day
|
||||||
|
|
||||||
|
DEFINE_REFRESH_TIME.put(70520009,12*HOUR);//薄荷 12 Hours
|
||||||
|
DEFINE_REFRESH_TIME.put(70520005,12*HOUR);//甜甜花 12 Hours
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static HashMap<Integer, List<CollectionData>> CollectionResourcesData = new HashMap<>();
|
||||||
|
private final HashMap<CollectionData,EntityGadget> spawnedEntities = new HashMap<>();
|
||||||
|
private CollectionRecordStore collectionRecordStore;
|
||||||
|
Player player;
|
||||||
|
|
||||||
|
private static long getGadgetRefreshTime(int gadgetId){
|
||||||
|
return DEFINE_REFRESH_TIME.getOrDefault(gadgetId,DEFAULT_REFRESH_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setPlayer(Player player) {
|
||||||
|
this.player = player;
|
||||||
|
this.collectionRecordStore = player.getCollectionRecordStore();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
package emu.grasscutter.game.managers.collection;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import dev.morphia.annotations.Entity;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class CollectionRecordStore {
|
||||||
|
private Map<Integer, CollectionRecord> records;
|
||||||
|
|
||||||
|
private Map<Integer, CollectionRecord> getRecords() {
|
||||||
|
if (records == null) {
|
||||||
|
records = new HashMap<>();
|
||||||
|
}
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRecord(int configId, long expiredMillisecond){
|
||||||
|
Map<Integer, CollectionRecord> records;
|
||||||
|
synchronized (records = getRecords()) {
|
||||||
|
records.put(configId, new CollectionRecord(configId, expiredMillisecond + System.currentTimeMillis()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean findRecord(int configId) {
|
||||||
|
Map<Integer, CollectionRecord> records;
|
||||||
|
synchronized (records = getRecords()) {
|
||||||
|
CollectionRecord record = records.get(configId);
|
||||||
|
|
||||||
|
if (record == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean expired = record.getExpiredTime() < System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (expired) {
|
||||||
|
records.remove(configId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public static class CollectionRecord {
|
||||||
|
private int configId;
|
||||||
|
private long expiredTime;
|
||||||
|
|
||||||
|
@Deprecated // Morphia
|
||||||
|
public CollectionRecord() {}
|
||||||
|
|
||||||
|
public CollectionRecord(int configId, long expiredTime) {
|
||||||
|
this.configId = configId;
|
||||||
|
this.expiredTime = expiredTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConfigId() {
|
||||||
|
return configId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getExpiredTime() {
|
||||||
|
return expiredTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,6 +32,8 @@ import emu.grasscutter.game.mail.MailHandler;
|
|||||||
import emu.grasscutter.game.managers.FurnitureManager;
|
import emu.grasscutter.game.managers.FurnitureManager;
|
||||||
import emu.grasscutter.game.managers.InsectCaptureManager;
|
import emu.grasscutter.game.managers.InsectCaptureManager;
|
||||||
import emu.grasscutter.game.managers.ResinManager;
|
import emu.grasscutter.game.managers.ResinManager;
|
||||||
|
import emu.grasscutter.game.managers.collection.CollectionManager;
|
||||||
|
import emu.grasscutter.game.managers.collection.CollectionRecordStore;
|
||||||
import emu.grasscutter.game.managers.deforestation.DeforestationManager;
|
import emu.grasscutter.game.managers.deforestation.DeforestationManager;
|
||||||
import emu.grasscutter.game.managers.energy.EnergyManager;
|
import emu.grasscutter.game.managers.energy.EnergyManager;
|
||||||
import emu.grasscutter.game.managers.forging.ActiveForgeData;
|
import emu.grasscutter.game.managers.forging.ActiveForgeData;
|
||||||
@ -42,7 +44,6 @@ import emu.grasscutter.game.managers.SotSManager;
|
|||||||
import emu.grasscutter.game.props.ActionReason;
|
import emu.grasscutter.game.props.ActionReason;
|
||||||
import emu.grasscutter.game.props.ClimateType;
|
import emu.grasscutter.game.props.ClimateType;
|
||||||
import emu.grasscutter.game.props.PlayerProperty;
|
import emu.grasscutter.game.props.PlayerProperty;
|
||||||
import emu.grasscutter.game.props.SceneType;
|
|
||||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||||
import emu.grasscutter.game.quest.QuestManager;
|
import emu.grasscutter.game.quest.QuestManager;
|
||||||
import emu.grasscutter.game.shop.ShopLimit;
|
import emu.grasscutter.game.shop.ShopLimit;
|
||||||
@ -62,7 +63,7 @@ import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
|
|||||||
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
|
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
|
||||||
import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture;
|
import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture;
|
||||||
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
|
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
|
||||||
|
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
|
||||||
import emu.grasscutter.server.event.player.PlayerJoinEvent;
|
import emu.grasscutter.server.event.player.PlayerJoinEvent;
|
||||||
import emu.grasscutter.server.event.player.PlayerQuitEvent;
|
import emu.grasscutter.server.event.player.PlayerQuitEvent;
|
||||||
import emu.grasscutter.server.game.GameServer;
|
import emu.grasscutter.server.game.GameServer;
|
||||||
@ -183,6 +184,9 @@ public class Player {
|
|||||||
@Transient private FurnitureManager furnitureManager;
|
@Transient private FurnitureManager furnitureManager;
|
||||||
@Transient private BattlePassManager battlePassManager;
|
@Transient private BattlePassManager battlePassManager;
|
||||||
|
|
||||||
|
@Transient private CollectionManager collectionManager;
|
||||||
|
private CollectionRecordStore collectionRecordStore;
|
||||||
|
|
||||||
private long springLastUsed;
|
private long springLastUsed;
|
||||||
private HashMap<String, MapMark> mapMarks;
|
private HashMap<String, MapMark> mapMarks;
|
||||||
private int nextResinRefresh;
|
private int nextResinRefresh;
|
||||||
@ -216,6 +220,7 @@ public class Player {
|
|||||||
this.flyCloakList = new HashSet<>();
|
this.flyCloakList = new HashSet<>();
|
||||||
this.costumeList = new HashSet<>();
|
this.costumeList = new HashSet<>();
|
||||||
this.towerData = new TowerData();
|
this.towerData = new TowerData();
|
||||||
|
this.collectionRecordStore = new CollectionRecordStore();
|
||||||
this.unlockedForgingBlueprints = new HashSet<>();
|
this.unlockedForgingBlueprints = new HashSet<>();
|
||||||
this.unlockedCombines = new HashSet<>();
|
this.unlockedCombines = new HashSet<>();
|
||||||
this.unlockedFurniture = new HashSet<>();
|
this.unlockedFurniture = new HashSet<>();
|
||||||
@ -1098,7 +1103,6 @@ public class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (entity instanceof EntityGadget gadget) {
|
} else if (entity instanceof EntityGadget gadget) {
|
||||||
|
|
||||||
if (gadget.getContent() == null) {
|
if (gadget.getContent() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1106,7 +1110,7 @@ public class Player {
|
|||||||
boolean shouldDelete = gadget.getContent().onInteract(this, opType);
|
boolean shouldDelete = gadget.getContent().onInteract(this, opType);
|
||||||
|
|
||||||
if (shouldDelete) {
|
if (shouldDelete) {
|
||||||
entity.getScene().removeEntity(entity);
|
entity.getScene().removeEntity(entity, VisionType.VISION_TYPE_REMOVE);
|
||||||
}
|
}
|
||||||
} else if (entity instanceof EntityMonster monster) {
|
} else if (entity instanceof EntityMonster monster) {
|
||||||
insectCaptureManager.arrestSmallCreature(monster);
|
insectCaptureManager.arrestSmallCreature(monster);
|
||||||
@ -1306,6 +1310,20 @@ public class Player {
|
|||||||
return deforestationManager;
|
return deforestationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CollectionManager getCollectionManager() {
|
||||||
|
if(this.collectionManager==null){
|
||||||
|
this.collectionManager = new CollectionManager();
|
||||||
|
}
|
||||||
|
return this.collectionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CollectionRecordStore getCollectionRecordStore() {
|
||||||
|
if(this.collectionRecordStore==null){
|
||||||
|
this.collectionRecordStore = new CollectionRecordStore();
|
||||||
|
}
|
||||||
|
return collectionRecordStore;
|
||||||
|
}
|
||||||
|
|
||||||
public HashMap<String, MapMark> getMapMarks() { return mapMarks; }
|
public HashMap<String, MapMark> getMapMarks() { return mapMarks; }
|
||||||
|
|
||||||
public void setMapMarks(HashMap<String, MapMark> newMarks) { mapMarks = newMarks; }
|
public void setMapMarks(HashMap<String, MapMark> newMarks) { mapMarks = newMarks; }
|
||||||
@ -1432,6 +1450,7 @@ public class Player {
|
|||||||
}
|
}
|
||||||
//Make sure towerManager's player is online player
|
//Make sure towerManager's player is online player
|
||||||
this.getTowerManager().setPlayer(this);
|
this.getTowerManager().setPlayer(this);
|
||||||
|
this.getCollectionManager().setPlayer(this);
|
||||||
|
|
||||||
// Load from db
|
// Load from db
|
||||||
this.getAvatars().loadFromDatabase();
|
this.getAvatars().loadFromDatabase();
|
||||||
@ -1485,7 +1504,6 @@ public class Player {
|
|||||||
session.send(new PacketCombineDataNotify(this.unlockedCombines));
|
session.send(new PacketCombineDataNotify(this.unlockedCombines));
|
||||||
this.forgingManager.sendForgeDataNotify();
|
this.forgingManager.sendForgeDataNotify();
|
||||||
this.resinManager.onPlayerLogin();
|
this.resinManager.onPlayerLogin();
|
||||||
|
|
||||||
getTodayMoonCard(); // The timer works at 0:0, some users log in after that, use this method to check if they have received a reward today or not. If not, send the reward.
|
getTodayMoonCard(); // The timer works at 0:0, some users log in after that, use this method to check if they have received a reward today or not. If not, send the reward.
|
||||||
|
|
||||||
// Battle Pass trigger
|
// Battle Pass trigger
|
||||||
|
@ -217,7 +217,7 @@ public class Scene {
|
|||||||
getPlayers().add(player);
|
getPlayers().add(player);
|
||||||
player.setSceneId(this.getId());
|
player.setSceneId(this.getId());
|
||||||
player.setScene(this);
|
player.setScene(this);
|
||||||
|
|
||||||
this.setupPlayerAvatars(player);
|
this.setupPlayerAvatars(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,13 +428,22 @@ public class Scene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getEntityLevel(int baseLevel, int worldLevelOverride) {
|
||||||
|
int level = worldLevelOverride > 0 ? worldLevelOverride + baseLevel - 22 : baseLevel;
|
||||||
|
level = level >= 100 ? 100 : level;
|
||||||
|
level = level <= 0 ? 1 : level;
|
||||||
|
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO - Test
|
// TODO - Test
|
||||||
public void checkSpawns() {
|
public synchronized void checkSpawns() {
|
||||||
SpatialIndex<SpawnGroupEntry> list = GameDepot.getSpawnListById(this.getId());
|
SpatialIndex<SpawnGroupEntry> list = GameDepot.getSpawnListById(this.getId());
|
||||||
Set<SpawnDataEntry> visible = new HashSet<>();
|
Set<SpawnDataEntry> visible = new HashSet<>();
|
||||||
|
|
||||||
for (Player player : this.getPlayers()) {
|
for (Player player : this.getPlayers()) {
|
||||||
int RANGE = 100;
|
int RANGE = 100;
|
||||||
|
|
||||||
Collection<SpawnGroupEntry> entries = list.query(
|
Collection<SpawnGroupEntry> entries = list.query(
|
||||||
new double[] {player.getPos().getX() - RANGE, player.getPos().getZ() - RANGE},
|
new double[] {player.getPos().getX() - RANGE, player.getPos().getZ() - RANGE},
|
||||||
new double[] {player.getPos().getX() + RANGE, player.getPos().getZ() + RANGE}
|
new double[] {player.getPos().getX() + RANGE, player.getPos().getZ() + RANGE}
|
||||||
@ -460,29 +469,45 @@ public class Scene {
|
|||||||
List<GameEntity> toRemove = new LinkedList<>();
|
List<GameEntity> toRemove = new LinkedList<>();
|
||||||
|
|
||||||
for (SpawnDataEntry entry : visible) {
|
for (SpawnDataEntry entry : visible) {
|
||||||
|
// If spawn entry is in our view and hasnt been spawned/killed yet, we should spawn it
|
||||||
if (!this.getSpawnedEntities().contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) {
|
if (!this.getSpawnedEntities().contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) {
|
||||||
// Spawn entity
|
// Entity object holder
|
||||||
MonsterData data = GameData.getMonsterDataMap().get(entry.getMonsterId());
|
GameEntity entity = null;
|
||||||
|
|
||||||
if (data == null) {
|
// Check if spawn entry is monster or gadget
|
||||||
continue;
|
if (entry.getMonsterId() > 0) {
|
||||||
|
MonsterData data = GameData.getMonsterDataMap().get(entry.getMonsterId());
|
||||||
|
if (data == null) continue;
|
||||||
|
|
||||||
|
int level = this.getEntityLevel(entry.getLevel(), worldLevelOverride);
|
||||||
|
|
||||||
|
EntityMonster monster = new EntityMonster(this, data, entry.getPos(), level);
|
||||||
|
monster.getRotation().set(entry.getRot());
|
||||||
|
monster.setGroupId(entry.getGroup().getGroupId());
|
||||||
|
monster.setPoseId(entry.getPoseId());
|
||||||
|
monster.setConfigId(entry.getConfigId());
|
||||||
|
monster.setSpawnEntry(entry);
|
||||||
|
|
||||||
|
entity = monster;
|
||||||
|
} else if (entry.getGadgetId() > 0) {
|
||||||
|
EntityGadget gadget = new EntityGadget(this, entry.getGadgetId(), entry.getPos(), entry.getRot());
|
||||||
|
gadget.setGroupId(entry.getGroup().getGroupId());
|
||||||
|
gadget.setConfigId(entry.getConfigId());
|
||||||
|
gadget.setSpawnEntry(entry);
|
||||||
|
gadget.buildContent();
|
||||||
|
|
||||||
|
gadget.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, 99999);
|
||||||
|
gadget.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 99999);
|
||||||
|
gadget.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, 99999);
|
||||||
|
|
||||||
|
entity = gadget;
|
||||||
}
|
}
|
||||||
|
|
||||||
int level = worldLevelOverride > 0 ? worldLevelOverride + entry.getLevel() - 22 : entry.getLevel();
|
if (entity == null) continue;
|
||||||
level = level >= 100 ? 100 : level;
|
|
||||||
level = level <= 0 ? 1 : level;
|
|
||||||
|
|
||||||
EntityMonster entity = new EntityMonster(this, data, entry.getPos(), level);
|
|
||||||
entity.getRotation().set(entry.getRot());
|
|
||||||
entity.setGroupId(entry.getGroup().getGroupId());
|
|
||||||
entity.setPoseId(entry.getPoseId());
|
|
||||||
entity.setConfigId(entry.getConfigId());
|
|
||||||
entity.setSpawnEntry(entry);
|
|
||||||
|
|
||||||
|
// Add to scene and spawned list
|
||||||
toAdd.add(entity);
|
toAdd.add(entity);
|
||||||
|
getSpawnedEntities().add(entry);
|
||||||
// Add to spawned list
|
|
||||||
this.getSpawnedEntities().add(entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package emu.grasscutter.game.world;
|
package emu.grasscutter.game.world;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import emu.grasscutter.utils.Position;
|
import emu.grasscutter.utils.Position;
|
||||||
@ -8,9 +7,11 @@ import emu.grasscutter.utils.Position;
|
|||||||
public class SpawnDataEntry {
|
public class SpawnDataEntry {
|
||||||
private transient SpawnGroupEntry group;
|
private transient SpawnGroupEntry group;
|
||||||
private int monsterId;
|
private int monsterId;
|
||||||
|
private int gadgetId;
|
||||||
private int configId;
|
private int configId;
|
||||||
private int level;
|
private int level;
|
||||||
private int poseId;
|
private int poseId;
|
||||||
|
private int gatherItemId;
|
||||||
private Position pos;
|
private Position pos;
|
||||||
private Position rot;
|
private Position rot;
|
||||||
|
|
||||||
@ -26,6 +27,10 @@ public class SpawnDataEntry {
|
|||||||
return monsterId;
|
return monsterId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getGadgetId() {
|
||||||
|
return gadgetId;
|
||||||
|
}
|
||||||
|
|
||||||
public int getConfigId() {
|
public int getConfigId() {
|
||||||
return configId;
|
return configId;
|
||||||
}
|
}
|
||||||
@ -38,6 +43,10 @@ public class SpawnDataEntry {
|
|||||||
return poseId;
|
return poseId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getGatherItemId() {
|
||||||
|
return gatherItemId;
|
||||||
|
}
|
||||||
|
|
||||||
public Position getPos() {
|
public Position getPos() {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
package emu.grasscutter.server.packet.recv;
|
package emu.grasscutter.server.packet.recv;
|
||||||
|
|
||||||
|
import emu.grasscutter.game.entity.EntityBaseGadget;
|
||||||
|
import emu.grasscutter.game.entity.GameEntity;
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
|
import emu.grasscutter.game.world.Scene;
|
||||||
import emu.grasscutter.net.packet.Opcodes;
|
import emu.grasscutter.net.packet.Opcodes;
|
||||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||||
import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvocationsNotify;
|
import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvocationsNotify;
|
||||||
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
|
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
|
||||||
import emu.grasscutter.net.packet.PacketHandler;
|
import emu.grasscutter.net.packet.PacketHandler;
|
||||||
|
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass;
|
||||||
|
import emu.grasscutter.net.proto.VisionTypeOuterClass;
|
||||||
import emu.grasscutter.server.game.GameSession;
|
import emu.grasscutter.server.game.GameSession;
|
||||||
|
import emu.grasscutter.server.packet.send.PacketSceneEntityDisappearNotify;
|
||||||
|
import emu.grasscutter.utils.Position;
|
||||||
import emu.grasscutter.utils.Utils;
|
import emu.grasscutter.utils.Utils;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||||
|
|
||||||
@Opcodes(PacketOpcodes.AbilityInvocationsNotify)
|
@Opcodes(PacketOpcodes.AbilityInvocationsNotify)
|
||||||
public class HandlerAbilityInvocationsNotify extends PacketHandler {
|
public class HandlerAbilityInvocationsNotify extends PacketHandler {
|
||||||
@ -14,10 +23,11 @@ public class HandlerAbilityInvocationsNotify extends PacketHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||||
AbilityInvocationsNotify notif = AbilityInvocationsNotify.parseFrom(payload);
|
AbilityInvocationsNotify notif = AbilityInvocationsNotify.parseFrom(payload);
|
||||||
|
|
||||||
|
Player player = session.getPlayer();
|
||||||
for (AbilityInvokeEntry entry : notif.getInvokesList()) {
|
for (AbilityInvokeEntry entry : notif.getInvokesList()) {
|
||||||
session.getPlayer().getAbilityManager().onAbilityInvoke(entry);
|
player.getAbilityManager().onAbilityInvoke(entry);
|
||||||
session.getPlayer().getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry);
|
player.getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package emu.grasscutter.server.packet.recv;
|
package emu.grasscutter.server.packet.recv;
|
||||||
|
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
import emu.grasscutter.net.packet.Opcodes;
|
import emu.grasscutter.net.packet.Opcodes;
|
||||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||||
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
|
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
|
||||||
@ -14,10 +15,11 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||||
ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload);
|
ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload);
|
||||||
|
|
||||||
|
Player player = session.getPlayer();
|
||||||
for (AbilityInvokeEntry entry : notif.getInvokesList()) {
|
for (AbilityInvokeEntry entry : notif.getInvokesList()) {
|
||||||
session.getPlayer().getAbilityManager().onAbilityInvoke(entry);
|
player.getAbilityManager().onAbilityInvoke(entry);
|
||||||
session.getPlayer().getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry);
|
player.getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notif.getInvokesList().size() > 0) {
|
if (notif.getInvokesList().size() > 0) {
|
||||||
|
@ -2,9 +2,12 @@ package emu.grasscutter.server.packet.recv;
|
|||||||
|
|
||||||
import emu.grasscutter.Grasscutter;
|
import emu.grasscutter.Grasscutter;
|
||||||
import emu.grasscutter.game.entity.GameEntity;
|
import emu.grasscutter.game.entity.GameEntity;
|
||||||
|
import emu.grasscutter.game.player.Player;
|
||||||
import emu.grasscutter.game.props.FightProperty;
|
import emu.grasscutter.game.props.FightProperty;
|
||||||
import emu.grasscutter.net.packet.Opcodes;
|
import emu.grasscutter.net.packet.Opcodes;
|
||||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||||
|
import emu.grasscutter.net.proto.AttackResultOuterClass;
|
||||||
|
import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
|
||||||
import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify;
|
import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify;
|
||||||
import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry;
|
import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry;
|
||||||
import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo;
|
import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo;
|
||||||
@ -32,10 +35,13 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
|
|||||||
for (CombatInvokeEntry entry : notif.getInvokeListList()) {
|
for (CombatInvokeEntry entry : notif.getInvokeListList()) {
|
||||||
switch (entry.getArgumentType()) {
|
switch (entry.getArgumentType()) {
|
||||||
case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT:
|
case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT:
|
||||||
// Handle damage
|
|
||||||
EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData());
|
EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData());
|
||||||
session.getPlayer().getAttackResults().add(hitInfo.getAttackResult());
|
AttackResult attackResult = hitInfo.getAttackResult();
|
||||||
session.getPlayer().getEnergyManager().handleAttackHit(hitInfo);
|
Player player = session.getPlayer();
|
||||||
|
|
||||||
|
// Handle damage
|
||||||
|
player.getAttackResults().add(attackResult);
|
||||||
|
player.getEnergyManager().handleAttackHit(hitInfo);
|
||||||
break;
|
break;
|
||||||
case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE:
|
case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE:
|
||||||
// Handle movement
|
// Handle movement
|
||||||
|
@ -5,6 +5,7 @@ import emu.grasscutter.net.packet.BasePacket;
|
|||||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||||
import emu.grasscutter.net.proto.GadgetInteractRspOuterClass.GadgetInteractRsp;
|
import emu.grasscutter.net.proto.GadgetInteractRspOuterClass.GadgetInteractRsp;
|
||||||
import emu.grasscutter.net.proto.InterOpTypeOuterClass;
|
import emu.grasscutter.net.proto.InterOpTypeOuterClass;
|
||||||
|
import emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType;
|
||||||
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
|
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
|
||||||
import emu.grasscutter.net.proto.RetcodeOuterClass;
|
import emu.grasscutter.net.proto.RetcodeOuterClass;
|
||||||
|
|
||||||
@ -12,7 +13,8 @@ public class PacketGadgetInteractRsp extends BasePacket {
|
|||||||
public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact) {
|
public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact) {
|
||||||
this(gadget, interact, null);
|
this(gadget, interact, null);
|
||||||
}
|
}
|
||||||
public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact, InterOpTypeOuterClass.InterOpType opType) {
|
|
||||||
|
public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact, InterOpType opType) {
|
||||||
super(PacketOpcodes.GadgetInteractRsp);
|
super(PacketOpcodes.GadgetInteractRsp);
|
||||||
|
|
||||||
var proto = GadgetInteractRsp.newBuilder()
|
var proto = GadgetInteractRsp.newBuilder()
|
||||||
@ -20,7 +22,7 @@ public class PacketGadgetInteractRsp extends BasePacket {
|
|||||||
.setInteractType(interact)
|
.setInteractType(interact)
|
||||||
.setGadgetId(gadget.getGadgetId());
|
.setGadgetId(gadget.getGadgetId());
|
||||||
|
|
||||||
if(opType != null){
|
if (opType != null) {
|
||||||
proto.setOpType(opType);
|
proto.setOpType(opType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,9 +135,20 @@ public class Position implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean equal2d(Position other) {
|
public boolean equal2d(Position other) {
|
||||||
return getX() == other.getX() && getY() == other.getY();
|
// Y is height
|
||||||
|
return getX() == other.getX() && getZ() == other.getZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equal3d(Position other) {
|
||||||
|
return getX() == other.getX() && getY() == other.getY() && getZ() == other.getZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double computeDistance(Position b){
|
||||||
|
double detX = getX()-b.getX();
|
||||||
|
double detY = getY()-b.getY();
|
||||||
|
double detZ = getZ()-b.getZ();
|
||||||
|
return Math.sqrt(detX*detX+detY*detY+detZ*detZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Position translateWithDegrees(float dist, float angle) {
|
public Position translateWithDegrees(float dist, float angle) {
|
||||||
angle = (float) Math.toRadians(angle);
|
angle = (float) Math.toRadians(angle);
|
||||||
this.x += dist * Math.sin(angle);
|
this.x += dist * Math.sin(angle);
|
||||||
|
1
src/main/resources/defaults/data/GadgetSpawns.json
Normal file
1
src/main/resources/defaults/data/GadgetSpawns.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user