mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-17 01:15:52 +01: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:
@@ -16,8 +16,11 @@ import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.entity.EntityClientGadget;
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.entity.EntityItem;
|
||||
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.props.ElementType;
|
||||
import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall;
|
||||
@@ -98,26 +101,36 @@ public class AbilityManager {
|
||||
}
|
||||
|
||||
private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception {
|
||||
// Sanity checks
|
||||
GameEntity target = player.getScene().getEntityById(invoke.getEntityId());
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AbilityInvokeEntryHead head = invoke.getHead();
|
||||
if (head == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AbilityMetaModifierChange data = AbilityMetaModifierChange.parseFrom(invoke.getAbilityData());
|
||||
if (data == null) {
|
||||
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());
|
||||
if (sourceEntity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 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) {
|
||||
// Handle add modifier here
|
||||
@@ -133,6 +146,7 @@ public class AbilityManager {
|
||||
// Add to meta modifier list
|
||||
target.getMetaModifiers().put(head.getInstancedModifierId(), modifierString);
|
||||
} else if (data.getAction() == ModifierAction.REMOVED) {
|
||||
// Handle remove modifier
|
||||
String modifierString = target.getMetaModifiers().get(head.getInstancedModifierId());
|
||||
|
||||
if (modifierString != null) {
|
||||
|
||||
@@ -8,11 +8,13 @@ import emu.grasscutter.game.props.EntityType;
|
||||
import emu.grasscutter.game.props.LifeState;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.SpawnDataEntry;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
||||
import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
|
||||
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.PropPairOuterClass.PropPair;
|
||||
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.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import lombok.ToString;
|
||||
|
||||
@@ -40,19 +43,24 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
private int state;
|
||||
private int pointType;
|
||||
private GadgetContent content;
|
||||
private Int2FloatOpenHashMap fightProp;
|
||||
private SceneGadget metaGadget;
|
||||
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos) {
|
||||
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot) {
|
||||
super(scene);
|
||||
this.data = GameData.getGadgetDataMap().get(gadgetId);
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.gadgetId = gadgetId;
|
||||
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) {
|
||||
this(scene, gadgetId, pos);
|
||||
|
||||
public EntityGadget(Scene scene, int gadgetId, Position 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;
|
||||
}
|
||||
|
||||
@@ -126,6 +134,7 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
EntityType type = getGadgetData().getType();
|
||||
GadgetContent content = switch (type) {
|
||||
case GatherPoint -> new GadgetGatherPoint(this);
|
||||
case GatherObject -> new GadgetGatherObject(this);
|
||||
case Worktop -> new GadgetWorktop(this);
|
||||
case RewardStatue -> new GadgetRewardStatue(this);
|
||||
case Chest -> new GadgetChest(this);
|
||||
@@ -137,7 +146,8 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
|
||||
@Override
|
||||
public Int2FloatOpenHashMap getFightProperties() {
|
||||
return null;
|
||||
if (this.fightProp == null) this.fightProp = new Int2FloatOpenHashMap();
|
||||
return this.fightProp;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,7 +158,10 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
|
||||
@Override
|
||||
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().getScriptManager().callEvent(EventType.EVENT_ANY_GADGET_DIE, new ScriptArgs(this.getConfigId()));
|
||||
@@ -178,6 +191,11 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
.build();
|
||||
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()
|
||||
.setGadgetId(this.getGadgetId())
|
||||
.setGroupId(this.getGroupId())
|
||||
|
||||
@@ -8,12 +8,14 @@ import emu.grasscutter.game.props.LifeState;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.SpawnDataEntry;
|
||||
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.MotionStateOuterClass.MotionState;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
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.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
@@ -124,6 +126,16 @@ public abstract class GameEntity {
|
||||
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() {
|
||||
return blockId;
|
||||
}
|
||||
|
||||
@@ -2,13 +2,12 @@ package emu.grasscutter.game.entity.gadget;
|
||||
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.proto.InterOpTypeOuterClass;
|
||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
|
||||
public abstract class GadgetContent {
|
||||
private final EntityGadget gadget;
|
||||
|
||||
|
||||
public GadgetContent(EntityGadget 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.excels.GatherData;
|
||||
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.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
|
||||
public class GadgetGatherPoint extends GadgetContent {
|
||||
private GatherData gatherData;
|
||||
private int itemId;
|
||||
private boolean isForbidGuest;
|
||||
|
||||
public GadgetGatherPoint(EntityGadget gadget) {
|
||||
super(gadget);
|
||||
this.gatherData = GameData.getGatherDataMap().get(gadget.getPointType());
|
||||
}
|
||||
|
||||
public GatherData getGatherData() {
|
||||
return gatherData;
|
||||
|
||||
if (gadget.getSpawnEntry() != null) {
|
||||
this.itemId = gadget.getSpawnEntry().getGatherItemId();
|
||||
} else {
|
||||
GatherData gatherData = GameData.getGatherDataMap().get(gadget.getPointType());
|
||||
this.itemId = gatherData.getItemId();
|
||||
this.isForbidGuest = gatherData.isForbidGuest();
|
||||
}
|
||||
}
|
||||
|
||||
public int getItemId() {
|
||||
return getGatherData().getItemId();
|
||||
return this.itemId;
|
||||
}
|
||||
|
||||
public boolean isForbidGuest() {
|
||||
return isForbidGuest;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -37,9 +49,33 @@ public class GadgetGatherPoint extends GadgetContent {
|
||||
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {
|
||||
GatherGadgetInfo gatherGadgetInfo = GatherGadgetInfo.newBuilder()
|
||||
.setItemId(this.getItemId())
|
||||
.setIsForbidGuest(this.getGatherData().isForbidGuest())
|
||||
.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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.InsectCaptureManager;
|
||||
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.energy.EnergyManager;
|
||||
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.ClimateType;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.props.SceneType;
|
||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||
import emu.grasscutter.game.quest.QuestManager;
|
||||
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.ProfilePictureOuterClass.ProfilePicture;
|
||||
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.PlayerQuitEvent;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
@@ -183,6 +184,9 @@ public class Player {
|
||||
@Transient private FurnitureManager furnitureManager;
|
||||
@Transient private BattlePassManager battlePassManager;
|
||||
|
||||
@Transient private CollectionManager collectionManager;
|
||||
private CollectionRecordStore collectionRecordStore;
|
||||
|
||||
private long springLastUsed;
|
||||
private HashMap<String, MapMark> mapMarks;
|
||||
private int nextResinRefresh;
|
||||
@@ -216,6 +220,7 @@ public class Player {
|
||||
this.flyCloakList = new HashSet<>();
|
||||
this.costumeList = new HashSet<>();
|
||||
this.towerData = new TowerData();
|
||||
this.collectionRecordStore = new CollectionRecordStore();
|
||||
this.unlockedForgingBlueprints = new HashSet<>();
|
||||
this.unlockedCombines = new HashSet<>();
|
||||
this.unlockedFurniture = new HashSet<>();
|
||||
@@ -1098,7 +1103,6 @@ public class Player {
|
||||
}
|
||||
}
|
||||
} else if (entity instanceof EntityGadget gadget) {
|
||||
|
||||
if (gadget.getContent() == null) {
|
||||
return;
|
||||
}
|
||||
@@ -1106,7 +1110,7 @@ public class Player {
|
||||
boolean shouldDelete = gadget.getContent().onInteract(this, opType);
|
||||
|
||||
if (shouldDelete) {
|
||||
entity.getScene().removeEntity(entity);
|
||||
entity.getScene().removeEntity(entity, VisionType.VISION_TYPE_REMOVE);
|
||||
}
|
||||
} else if (entity instanceof EntityMonster monster) {
|
||||
insectCaptureManager.arrestSmallCreature(monster);
|
||||
@@ -1306,6 +1310,20 @@ public class Player {
|
||||
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 void setMapMarks(HashMap<String, MapMark> newMarks) { mapMarks = newMarks; }
|
||||
@@ -1432,6 +1450,7 @@ public class Player {
|
||||
}
|
||||
//Make sure towerManager's player is online player
|
||||
this.getTowerManager().setPlayer(this);
|
||||
this.getCollectionManager().setPlayer(this);
|
||||
|
||||
// Load from db
|
||||
this.getAvatars().loadFromDatabase();
|
||||
@@ -1485,7 +1504,6 @@ public class Player {
|
||||
session.send(new PacketCombineDataNotify(this.unlockedCombines));
|
||||
this.forgingManager.sendForgeDataNotify();
|
||||
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.
|
||||
|
||||
// Battle Pass trigger
|
||||
|
||||
@@ -217,7 +217,7 @@ public class Scene {
|
||||
getPlayers().add(player);
|
||||
player.setSceneId(this.getId());
|
||||
player.setScene(this);
|
||||
|
||||
|
||||
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
|
||||
public void checkSpawns() {
|
||||
public synchronized void checkSpawns() {
|
||||
SpatialIndex<SpawnGroupEntry> list = GameDepot.getSpawnListById(this.getId());
|
||||
Set<SpawnDataEntry> visible = new HashSet<>();
|
||||
|
||||
|
||||
for (Player player : this.getPlayers()) {
|
||||
int RANGE = 100;
|
||||
|
||||
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}
|
||||
@@ -460,29 +469,45 @@ public class Scene {
|
||||
List<GameEntity> toRemove = new LinkedList<>();
|
||||
|
||||
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)) {
|
||||
// Spawn entity
|
||||
MonsterData data = GameData.getMonsterDataMap().get(entry.getMonsterId());
|
||||
// Entity object holder
|
||||
GameEntity entity = null;
|
||||
|
||||
if (data == null) {
|
||||
continue;
|
||||
// Check if spawn entry is monster or gadget
|
||||
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();
|
||||
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);
|
||||
if (entity == null) continue;
|
||||
|
||||
// Add to scene and spawned list
|
||||
toAdd.add(entity);
|
||||
|
||||
// Add to spawned list
|
||||
this.getSpawnedEntities().add(entry);
|
||||
getSpawnedEntities().add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package emu.grasscutter.game.world;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import emu.grasscutter.utils.Position;
|
||||
@@ -8,9 +7,11 @@ import emu.grasscutter.utils.Position;
|
||||
public class SpawnDataEntry {
|
||||
private transient SpawnGroupEntry group;
|
||||
private int monsterId;
|
||||
private int gadgetId;
|
||||
private int configId;
|
||||
private int level;
|
||||
private int poseId;
|
||||
private int gatherItemId;
|
||||
private Position pos;
|
||||
private Position rot;
|
||||
|
||||
@@ -26,6 +27,10 @@ public class SpawnDataEntry {
|
||||
return monsterId;
|
||||
}
|
||||
|
||||
public int getGadgetId() {
|
||||
return gadgetId;
|
||||
}
|
||||
|
||||
public int getConfigId() {
|
||||
return configId;
|
||||
}
|
||||
@@ -38,6 +43,10 @@ public class SpawnDataEntry {
|
||||
return poseId;
|
||||
}
|
||||
|
||||
public int getGatherItemId() {
|
||||
return gatherItemId;
|
||||
}
|
||||
|
||||
public Position getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user