mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-01-10 04:32:53 +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;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
@ -27,6 +28,7 @@ import emu.grasscutter.data.common.PointData;
|
||||
import emu.grasscutter.data.common.ScenePointConfig;
|
||||
import emu.grasscutter.game.world.SpawnDataEntry.*;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
import static emu.grasscutter.Configuration.*;
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
@ -306,19 +308,32 @@ public class ResourceLoader {
|
||||
}
|
||||
|
||||
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
|
||||
try(InputStream spawnDataEntries = DataLoader.load("Spawns.json")) {
|
||||
spawnEntryList = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(spawnDataEntries), TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType());
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
if (spawnEntryList == null || spawnEntryList.isEmpty()) {
|
||||
for (String name : spawnDataNames) {
|
||||
// Load spawn entries from file
|
||||
try (InputStream spawnDataEntries = DataLoader.load(name)) {
|
||||
Type type = TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType();
|
||||
List<SpawnGroupEntry> list = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(spawnDataEntries), type);
|
||||
|
||||
// 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!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (SpawnGroupEntry entry : spawnEntryList) {
|
||||
for (SpawnGroupEntry entry : spawnEntryMap.values()) {
|
||||
entry.getSpawns().forEach(s -> s.setGroup(entry));
|
||||
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.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;
|
||||
}
|
||||
|
@ -1,12 +1,21 @@
|
||||
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.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvocationsNotify;
|
||||
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
|
||||
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.packet.send.PacketSceneEntityDisappearNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
|
||||
@Opcodes(PacketOpcodes.AbilityInvocationsNotify)
|
||||
public class HandlerAbilityInvocationsNotify extends PacketHandler {
|
||||
@ -14,10 +23,11 @@ public class HandlerAbilityInvocationsNotify extends PacketHandler {
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
AbilityInvocationsNotify notif = AbilityInvocationsNotify.parseFrom(payload);
|
||||
|
||||
|
||||
Player player = session.getPlayer();
|
||||
for (AbilityInvokeEntry entry : notif.getInvokesList()) {
|
||||
session.getPlayer().getAbilityManager().onAbilityInvoke(entry);
|
||||
session.getPlayer().getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry);
|
||||
player.getAbilityManager().onAbilityInvoke(entry);
|
||||
player.getAbilityInvokeHandler().addEntry(entry.getForwardType(), entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry;
|
||||
@ -14,10 +15,11 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload);
|
||||
|
||||
|
||||
Player player = session.getPlayer();
|
||||
for (AbilityInvokeEntry entry : notif.getInvokesList()) {
|
||||
session.getPlayer().getAbilityManager().onAbilityInvoke(entry);
|
||||
session.getPlayer().getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry);
|
||||
player.getAbilityManager().onAbilityInvoke(entry);
|
||||
player.getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry);
|
||||
}
|
||||
|
||||
if (notif.getInvokesList().size() > 0) {
|
||||
|
@ -2,9 +2,12 @@ package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
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.CombatInvokeEntryOuterClass.CombatInvokeEntry;
|
||||
import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo;
|
||||
@ -32,10 +35,13 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
|
||||
for (CombatInvokeEntry entry : notif.getInvokeListList()) {
|
||||
switch (entry.getArgumentType()) {
|
||||
case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT:
|
||||
// Handle damage
|
||||
EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData());
|
||||
session.getPlayer().getAttackResults().add(hitInfo.getAttackResult());
|
||||
session.getPlayer().getEnergyManager().handleAttackHit(hitInfo);
|
||||
AttackResult attackResult = hitInfo.getAttackResult();
|
||||
Player player = session.getPlayer();
|
||||
|
||||
// Handle damage
|
||||
player.getAttackResults().add(attackResult);
|
||||
player.getEnergyManager().handleAttackHit(hitInfo);
|
||||
break;
|
||||
case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE:
|
||||
// Handle movement
|
||||
|
@ -5,6 +5,7 @@ import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.GadgetInteractRspOuterClass.GadgetInteractRsp;
|
||||
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.RetcodeOuterClass;
|
||||
|
||||
@ -12,7 +13,8 @@ public class PacketGadgetInteractRsp extends BasePacket {
|
||||
public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact) {
|
||||
this(gadget, interact, null);
|
||||
}
|
||||
public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact, InterOpTypeOuterClass.InterOpType opType) {
|
||||
|
||||
public PacketGadgetInteractRsp(EntityBaseGadget gadget, InteractType interact, InterOpType opType) {
|
||||
super(PacketOpcodes.GadgetInteractRsp);
|
||||
|
||||
var proto = GadgetInteractRsp.newBuilder()
|
||||
@ -20,7 +22,7 @@ public class PacketGadgetInteractRsp extends BasePacket {
|
||||
.setInteractType(interact)
|
||||
.setGadgetId(gadget.getGadgetId());
|
||||
|
||||
if(opType != null){
|
||||
if (opType != null) {
|
||||
proto.setOpType(opType);
|
||||
}
|
||||
|
||||
|
@ -135,9 +135,20 @@ public class Position implements Serializable {
|
||||
}
|
||||
|
||||
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) {
|
||||
angle = (float) Math.toRadians(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