mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-14 07:55:57 +01:00
Merge unstable into development (#2173)
* Remove more scene synchronized
* Fix worktop options not appearing
* Format code [skip actions]
* Fix delay with server tasks
* Format code [skip actions]
* Fully fix fairy clock (#2146)
* Fix scene transition
* fully fix fairy clock
* Re-add call to `Player#updatePlayerGameTime`
* Format code [skip actions]
* Initialize the script loader in `ResourceLoader#loadAll`
* Fix region removal checking
* Format code [skip actions]
* Use Lombok's `EqualsAndHashCode` for comparing scene regions
* Format code [skip actions]
* Move 'invalid gather object' to `trace`
* Add more information to the 'unknown condition handler' message
* Move invalid ability action to trace
* Make `KcpTunnel` public
* Validate the NPC being talked to
* Format code [skip actions]
* NPCs are not spawned server side; change logic to handle it
* Format code [skip actions]
* unload scene when there are no players (#2147)
* unload scene when there are no players
* Update src/main/java/emu/grasscutter/game/world/Scene.java
Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
---------
Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
* Check if a command should be copied or HTTP should be used
* Lint Code [skip actions]
* Fix character names rendering incorrectly
* Add basic troubleshooting command
* Implement handbook teleporting
also a few formatting changes and sort data by logical sense
* Fix listener `ConcurrentModificationException` issue
* Add color change to `Join the Community!`
* Lint Code [skip actions]
* Make clickable buttons appear clickable
* Remove 'Mechanicus' entities from the list of entities
* Format code [skip actions]
* Fix going back returning a blank screen
* Implement entity spawning
* Add setting level to entity card
* Add support for 'plain text' mode
* Make descriptions of objects scrollable
* Lint Code [skip actions]
* Format code [skip actions]
* Change the way existing hooks work
* Format code [skip actions]
* Upgrade Javalin to 5.5.0 & Fix project warnings
* Upgrade logging libraries
* Fix gacha mappings static file issue
* Add temporary backwards compatability for `ServerHelper`
* Format code [skip actions]
* Remove artifact signatures from VCS
* Fix forge queue data protocol definition
* Run `spotlessApply`
* Format code [skip actions]
* Download data required for building artifacts
* Add call for Facebook logins
* Add the wiki page as a submodule
* Format code [skip actions]
* Update translation (#2150)
* Update translation
* Update translation
* Separate the dispatch and game servers (pt. 1)
gacha is still broken, handbook still needs to be done
* Format code [skip actions]
* Separate the dispatch and game servers (pt. 2)
this commit fixes the gacha page
* Add description for '/troubleshoot'
* Set default avatar talent level to 10
* Separate the dispatch and game servers (pt. 3)
implement handbook across servers!
* Format code [skip actions]
* Update GitHub Actions to use 'download-file' over 'wget'
* Gm handbook lmao (#2149)
* Fix font issue
* Fix avatars
* Fix text overflow in commands
* Fix virtualized lists and items page 😭😭
* magix why 💀
* use hover style in all minicards
* button
* remove console.log
* lint
* Add icons
* magix asked
* Fix overflow padding issue
* Fix achievement text overflow
* remove icons from repo
* Change command icon
* Add the wiki page as a submodule
* total magix moment
* fix text overflow in commands
* Fix discord button
* Make text scale on Minicard
* import icons and font from another source
* Add hover effects to siebar buttons
* move font and readme to submodule repo
* Make data folder a submodule
* import icons and font from data submodule
* Update README.md
* total magix moment
* magix moment v2
* submodule change
* Import `.webp` files
* Resize `HomeButton`
* Fix 'Copy Command' reappearing after changing pages
---------
Co-authored-by: KingRainbow44 <kobedo11@gmail.com>
* Lint Code [skip actions]
* Download data for the build, not for the lint
* format imports
this is really just to see if build handbook works kek
* Implement proper handbook authentication (pt. 1)
* Implement proper handbook authentication (pt. 2)
* Format code [skip actions]
* Add quest data dumping for the handbook
* Change colors to fit _something suitable_
* Format code [skip actions]
* Fix force pushing to branches after linting
* Fix logic of `SetPlayerPropReq`
* Move more group loading to `trace`
* Add handbook IP authentication in hybrid mode
* Fix player level up not displaying on the client properly
* Format code [skip actions]
* Fix game time locking
* Format code [skip actions]
* Update player properties
* Format code [skip actions]
* Move `warn`s for groups to `debug`
* Fix player pausing
* Move more logs to `trace`
* Use `removeItemById` for deleting items via quests
* Clean up logger more
* Pause in-game time when the world is paused
* Format code [skip actions]
* More player property documentation
* Multi-threaded resource loading
* Format code [skip actions]
* Add quest widgets
* Add quests page (basic impl.)
* Add/fix colors
also fix tailwind
* Remove banned packets
client modifications already perform the job of blocking malicious packets from being executed, no point in having this if self-windy is wanted
* Re-add `BeginCameraSceneLookNotify`
* Fix being unable to attack (#2157)
* Add `PlayerOpenChestEvent`
* Add methods to get players from the server
* Add static methods to register an event handler
* Add `PlayerEnterDungeonEvent`
* Remove legacy documentation from `PlayerMoveEvent`
* Add `PlayerChatEvent`
* Add defaults to `Position`
* Clean up `.utils`
* Revert `Multi-threaded resource loading`
* Fix changing target UID when talking to the server
* Lint Code [skip actions]
* Format code [skip actions]
* fix NPC talk triggering main quest in 46101 (#2158)
Make it so that only talks where the param matches the talkId are checked.
* Format code [skip actions]
* Partially fix Chasing Shadows (#2159)
* Partially fix Chasing Shadows
* Go ahead and move it before the return before Magix tells me to.
* Format code [skip actions]
* Bring back period lol (#2160)
* Disable SNI for the HTTPS server
* Add `EntityCreationEvent`
* Add initial startup message
this is so the server appears like its preparing to start
* Format code [skip actions]
* Enable debug mode for plugin loggers if enabled for the primary logger
* Add documentation about `WorldAreaConfigData`
* Make more fields in excels accessible
* Remove deprecated fields from `GetShopRsp`
* Run `spotlessApply` on definitions
* Add `PlayerEnterAreaEvent`
* Optimize event calls
* Fix event invokes
* Format code [skip actions]
* Remove manual autofinish for main quests. (#2162)
* Add world areas to the textmap cache
* Format code [skip actions]
* Don't overdefine variables in extended classes (#2163)
* Add dumper for world areas
* Format code [skip actions]
* instantiate personalLineList (#2165)
* Fix protocol definitions
thank you Nazrin! (+ hiro for raw definitions)
* Fix the background color leaking from the character widget
* Change HTML spacing to 2 spaces
* Implement hiding widgets
* Change scrollbar to a vibrant color
* Add _some_ scaling to the home buttons and its text
* Build the handbook with Gradle
* Fix the 'finer details' with the handbook UI
* Lint Code [skip actions]
* Fix target destination for the Gradle-built handbook
* Implement fetching a player across servers & Add a chainable JsonObject
useful for plugins! might be used in grasscutter eventually
* Fix GitHub actions
* Fix event calling & canceling
* Run `spotlessApply`
* Rename fields (might be wrong)
* Add/update all/more protocol definitions
* Add/update all/more protocol definitions
* Remove outdated packet
* Fix protocol definitions
* Format code [skip actions]
* Implement some lua variables for less console spam (#2172)
* Implement some lua variables for less console spam
* Add GetHostQuestState
This fixes some chapter 3 stuff.
* Format code [skip actions]
* Fix merge import
* Format code [skip actions]
* Fully fix fairy clock for real this time (#2167)
* Fully fix fairy clock For real this time
* Make it so relogging keeps the time lock state.
* Refactor out questLockTime
* Per Hartie, the client packet needs to be changed too
* Update src/main/java/emu/grasscutter/game/world/World.java
Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
* Update src/main/java/emu/grasscutter/server/packet/recv/HandlerClientLockGameTimeNotify.java
* Remove all code not needed to get clock working
---------
Co-authored-by: Magix <27646710+KingRainbow44@users.noreply.github.com>
* Implement a proper ability system (#2166)
* Apply fix `21dec2fe`
* Apply fix `89d01d5f`
* Apply fix `d900f154`
this one was already implemented; updated to use call from previous commit
* Ability changing commit
TODO: change info to debug
* Remove use of deprecated methods/fields
* Temp commit v2
(Adding LoseHP and some fixes)
* Oopsie
* Probably fix monster battle
* Fix issue with reflecting into fields
* Fix some things
* Fix ability names for 3.6 resources
* Improve logging
---------
Co-authored-by: StartForKiller <jesussanz2003@gmail.com>
* Format code [skip actions]
* Add system for sending messages between servers
* Format some code
* Remove protocol definitions from Spotless
* Default debug to false; enable with `-debug`
* Implement completely useless global value copying
* HACK: Return the avatar which holds the weapon when the weapon is referred to by ID
* Add properties to `AbilityModifier`
* Change the way HTML is served after authentication
* Use thread executors to speed up the database loading process
* Format code [skip actions]
* Add system for setting handbook address and port
* Lint Code [skip actions]
* Format code [skip actions]
* Fix game-related data not saving
* Format code [skip actions]
* Fix handbook server details
* Lint Code [skip actions]
* Format code [skip actions]
* Use the headers provided by a context to get the IP address
should acknowledge #1975
* Format code [skip actions]
* Move more logs to `trace`
* Format code [skip actions]
* more trace
* Fix something and implement weapon entities
* Format code [skip actions]
* Fix `EntityWeapon`
* Remove deprecated API & Fix resource checking
* Fix unnecessary warning for first-time setup
* Implement handbook request limiting
* Format code [skip actions]
* Fix new avatar weapons being null
* Format code [skip actions]
* Fix issue with 35303 being un-completable & Try to fix fulfilled quest conditions being met
* Load activity config on server startup
* Require plugins to specify an API version and match with the server
* Add default open state ignore list
* Format code [skip actions]
* Quick fix for questing, needs more investigation
This would make the questing work again
* Remove existing hack for 35303
* Fix ignored open states from being set
* Format code [skip actions]
* fix the stupidest bug ive ever seen
* Optimize player kicking on server close
* Format code [skip actions]
* Re-add hack to fix 35303
* Update GitHub actions
* Format code [skip actions]
* Potentially fix issues with regions
* Download additional handbook data
* Revert "Potentially fix issues with regions"
This reverts commit 84e3823695.
---------
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: scooterboo <lewasite@yahoo.com>
Co-authored-by: Tesutarin <105267106+Tesutarin@users.noreply.github.com>
Co-authored-by: Scald <104459145+Arikatsu@users.noreply.github.com>
Co-authored-by: StartForKiller <jesussanz2003@gmail.com>
This commit is contained in:
@@ -1,17 +1,14 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.*;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.AvatarData;
|
||||
import emu.grasscutter.data.excels.AvatarSkillDepotData;
|
||||
import emu.grasscutter.data.excels.avatar.*;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.inventory.EquipType;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.inventory.*;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.props.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.*;
|
||||
import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlock;
|
||||
import emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
@@ -30,15 +27,11 @@ import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import emu.grasscutter.server.event.player.PlayerMoveEvent;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import emu.grasscutter.server.packet.send.*;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import emu.grasscutter.utils.helpers.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import lombok.*;
|
||||
|
||||
public class EntityAvatar extends GameEntity {
|
||||
@Getter private final Avatar avatar;
|
||||
@@ -52,39 +45,68 @@ public class EntityAvatar extends GameEntity {
|
||||
|
||||
public EntityAvatar(Scene scene, Avatar avatar) {
|
||||
super(scene);
|
||||
|
||||
this.avatar = avatar;
|
||||
this.avatar.setCurrentEnergy();
|
||||
if (getScene() != null)
|
||||
{
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.AVATAR);
|
||||
|
||||
GameItem weapon = getAvatar().getWeapon();
|
||||
if (scene != null) {
|
||||
var world = scene.getWorld();
|
||||
this.id = world.getNextEntityId(EntityIdType.AVATAR);
|
||||
|
||||
var weapon = this.getAvatar().getWeapon();
|
||||
if (weapon != null) {
|
||||
weapon.setWeaponEntityId(getScene().getWorld().getNextEntityId(EntityIdType.WEAPON));
|
||||
if (!(weapon.getWeaponEntity() != null && weapon.getWeaponEntity().getScene() == scene)) {
|
||||
weapon.setWeaponEntity(
|
||||
new EntityWeapon(this.getPlayer().getScene(), weapon.getItemData().getGadgetId()));
|
||||
scene.getWeaponEntities().put(weapon.getWeaponEntity().getId(), weapon.getWeaponEntity());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Grasscutter.getLogger()
|
||||
.error("Unable to create EntityAvatar instance; provided scene is null.");
|
||||
}
|
||||
|
||||
this.initAbilities();
|
||||
}
|
||||
|
||||
public Player getPlayer() {return this.avatar.getPlayer();}
|
||||
@Override
|
||||
public int getEntityTypeId() {
|
||||
return this.getAvatar().getAvatarId();
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return this.avatar.getPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {return getPlayer().getPosition();}
|
||||
public Position getPosition() {
|
||||
return getPlayer().getPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {return getPlayer().getRotation();}
|
||||
public Position getRotation() {
|
||||
return getPlayer().getRotation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) > 0f;
|
||||
}
|
||||
|
||||
@Override public Int2FloatMap getFightProperties() {return getAvatar().getFightProperties();}
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
return getAvatar().getFightProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The entity ID of the avatar's equipped weapon.
|
||||
*/
|
||||
public int getWeaponEntityId() {
|
||||
if (getAvatar().getWeapon() != null) {
|
||||
return getAvatar().getWeapon().getWeaponEntityId();
|
||||
}
|
||||
return 0;
|
||||
var avatar = this.getAvatar();
|
||||
|
||||
if (avatar.getWeapon() != null && avatar.getWeapon().getWeaponEntity() != null) {
|
||||
return avatar.getWeapon().getWeaponEntity().getId();
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,23 +127,44 @@ public class EntityAvatar extends GameEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public float heal(float amount) {
|
||||
public void initAbilities() {}
|
||||
|
||||
private void addConfigAbility(String abilityName) {
|
||||
var data = GameData.getAbilityData(abilityName);
|
||||
if (data != null)
|
||||
this.getScene().getWorld().getHost().getAbilityManager().addAbilityToEntity(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float heal(float amount, boolean mute) {
|
||||
// Do not heal character if they are dead
|
||||
if (!this.isAlive()) {
|
||||
return 0f;
|
||||
}
|
||||
|
||||
float healed = super.heal(amount);
|
||||
float healed = super.heal(amount, mute);
|
||||
|
||||
if (healed > 0f) {
|
||||
getScene().broadcastPacket(
|
||||
new PacketEntityFightPropChangeReasonNotify(this, FightProperty.FIGHT_PROP_CUR_HP, healed, PropChangeReason.PROP_CHANGE_REASON_ABILITY, ChangeHpReason.CHANGE_HP_REASON_ADD_ABILITY)
|
||||
);
|
||||
getScene()
|
||||
.broadcastPacket(
|
||||
new PacketEntityFightPropChangeReasonNotify(
|
||||
this,
|
||||
FightProperty.FIGHT_PROP_CUR_HP,
|
||||
healed,
|
||||
mute
|
||||
? PropChangeReason.PROP_CHANGE_REASON_NONE
|
||||
: PropChangeReason.PROP_CHANGE_REASON_ABILITY,
|
||||
ChangeHpReason.CHANGE_HP_REASON_ADD_ABILITY));
|
||||
}
|
||||
|
||||
return healed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float heal(float amount) {
|
||||
return this.heal(amount, false);
|
||||
}
|
||||
|
||||
public void clearEnergy(ChangeEnergyReason reason) {
|
||||
// Fight props.
|
||||
val curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp();
|
||||
@@ -134,13 +177,32 @@ public class EntityAvatar extends GameEntity {
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, curEnergyProp));
|
||||
|
||||
if (reason == ChangeEnergyReason.CHANGE_ENERGY_REASON_SKILL_START) {
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, -curEnergy, reason));
|
||||
this.getScene()
|
||||
.broadcastPacket(
|
||||
new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, -curEnergy, reason));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a fixed amount of energy to the current avatar.
|
||||
*
|
||||
* @param amount The amount of energy to add.
|
||||
* @return True if the energy was added, false if the energy was not added.
|
||||
*/
|
||||
public boolean addEnergy(float amount) {
|
||||
var curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp();
|
||||
var curEnergy = this.getFightProperty(curEnergyProp);
|
||||
if (curEnergy == amount) return false;
|
||||
|
||||
this.getAvatar().setCurrentEnergy(curEnergyProp, amount);
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, curEnergyProp));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addEnergy(float amount, PropChangeReason reason) {
|
||||
this.addEnergy(amount, reason, false);
|
||||
}
|
||||
|
||||
public void addEnergy(float amount, PropChangeReason reason, boolean isFlat) {
|
||||
// Get current and maximum energy for this avatar.
|
||||
val elementType = this.getAvatar().getSkillDepot().getElementType();
|
||||
@@ -162,29 +224,33 @@ public class EntityAvatar extends GameEntity {
|
||||
if (newEnergy != curEnergy) {
|
||||
this.avatar.setCurrentEnergy(curEnergyProp, newEnergy);
|
||||
|
||||
this.getScene().broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp));
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, newEnergy, reason));
|
||||
this.getScene()
|
||||
.broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp));
|
||||
this.getScene()
|
||||
.broadcastPacket(
|
||||
new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, newEnergy, reason));
|
||||
}
|
||||
}
|
||||
|
||||
public SceneAvatarInfo getSceneAvatarInfo() {
|
||||
val avatar = this.getAvatar();
|
||||
val player = this.getPlayer();
|
||||
SceneAvatarInfo.Builder avatarInfo = SceneAvatarInfo.newBuilder()
|
||||
.setUid(player.getUid())
|
||||
.setAvatarId(avatar.getAvatarId())
|
||||
.setGuid(avatar.getGuid())
|
||||
.setPeerId(player.getPeerId())
|
||||
.addAllTalentIdList(avatar.getTalentIdList())
|
||||
.setCoreProudSkillLevel(avatar.getCoreProudSkillLevel())
|
||||
.putAllSkillLevelMap(avatar.getSkillLevelMap())
|
||||
.setSkillDepotId(avatar.getSkillDepotId())
|
||||
.addAllInherentProudSkillList(avatar.getProudSkillList())
|
||||
.putAllProudSkillExtraLevelMap(avatar.getProudSkillBonusMap())
|
||||
.addAllTeamResonanceList(player.getTeamManager().getTeamResonances())
|
||||
.setWearingFlycloakId(avatar.getFlyCloak())
|
||||
.setCostumeId(avatar.getCostume())
|
||||
.setBornTime(avatar.getBornTime());
|
||||
SceneAvatarInfo.Builder avatarInfo =
|
||||
SceneAvatarInfo.newBuilder()
|
||||
.setUid(player.getUid())
|
||||
.setAvatarId(avatar.getAvatarId())
|
||||
.setGuid(avatar.getGuid())
|
||||
.setPeerId(player.getPeerId())
|
||||
.addAllTalentIdList(avatar.getTalentIdList())
|
||||
.setCoreProudSkillLevel(avatar.getCoreProudSkillLevel())
|
||||
.putAllSkillLevelMap(avatar.getSkillLevelMap())
|
||||
.setSkillDepotId(avatar.getSkillDepotId())
|
||||
.addAllInherentProudSkillList(avatar.getProudSkillList())
|
||||
.putAllProudSkillExtraLevelMap(avatar.getProudSkillBonusMap())
|
||||
.addAllTeamResonanceList(player.getTeamManager().getTeamResonances())
|
||||
.setWearingFlycloakId(avatar.getFlyCloak())
|
||||
.setCostumeId(avatar.getCostume())
|
||||
.setBornTime(avatar.getBornTime());
|
||||
|
||||
for (GameItem item : avatar.getEquips().values()) {
|
||||
if (item.getItemData().getEquipType() == EquipType.EQUIP_WEAPON) {
|
||||
@@ -200,22 +266,25 @@ public class EntityAvatar extends GameEntity {
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
|
||||
.setBornPos(Vector.newBuilder())
|
||||
.build();
|
||||
EntityAuthorityInfo authority =
|
||||
EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(
|
||||
SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
|
||||
.setBornPos(Vector.newBuilder())
|
||||
.build();
|
||||
|
||||
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_AVATAR)
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLastMoveSceneTimeMs(this.getLastMoveSceneTimeMs())
|
||||
.setLastMoveReliableSeq(this.getLastMoveReliableSeq())
|
||||
.setLifeState(this.getLifeState().getValue());
|
||||
SceneEntityInfo.Builder entityInfo =
|
||||
SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_AVATAR)
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLastMoveSceneTimeMs(this.getLastMoveSceneTimeMs())
|
||||
.setLastMoveReliableSeq(this.getLastMoveReliableSeq())
|
||||
.setLifeState(this.getLifeState().getValue());
|
||||
|
||||
if (this.getScene() != null) {
|
||||
entityInfo.setMotionInfo(this.getMotionInfo());
|
||||
@@ -223,10 +292,12 @@ public class EntityAvatar extends GameEntity {
|
||||
|
||||
this.addAllFightPropsToEntityInfo(entityInfo);
|
||||
|
||||
PropPair pair = PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getAvatar().getLevel()))
|
||||
.build();
|
||||
PropPair pair =
|
||||
PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(
|
||||
ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getAvatar().getLevel()))
|
||||
.build();
|
||||
entityInfo.addPropList(pair);
|
||||
|
||||
entityInfo.setAvatar(this.getSceneAvatarInfo());
|
||||
@@ -242,52 +313,58 @@ public class EntityAvatar extends GameEntity {
|
||||
// Add avatar abilities
|
||||
if (data.getAbilities() != null) {
|
||||
for (int id : data.getAbilities()) {
|
||||
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(id)
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
AbilityEmbryo emb =
|
||||
AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(id)
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
abilityControlBlock.addAbilityEmbryoList(emb);
|
||||
}
|
||||
}
|
||||
// Add default abilities
|
||||
for (int id : GameConstants.DEFAULT_ABILITY_HASHES) {
|
||||
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(id)
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
AbilityEmbryo emb =
|
||||
AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(id)
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
abilityControlBlock.addAbilityEmbryoList(emb);
|
||||
}
|
||||
// Add team resonances
|
||||
for (int id : this.getPlayer().getTeamManager().getTeamResonancesConfig()) {
|
||||
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(id)
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
AbilityEmbryo emb =
|
||||
AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(id)
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
abilityControlBlock.addAbilityEmbryoList(emb);
|
||||
}
|
||||
// Add skill depot abilities
|
||||
AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(this.getAvatar().getSkillDepotId());
|
||||
AvatarSkillDepotData skillDepot =
|
||||
GameData.getAvatarSkillDepotDataMap().get(this.getAvatar().getSkillDepotId());
|
||||
if (skillDepot != null && skillDepot.getAbilities() != null) {
|
||||
for (int id : skillDepot.getAbilities()) {
|
||||
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(id)
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
AbilityEmbryo emb =
|
||||
AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(id)
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
abilityControlBlock.addAbilityEmbryoList(emb);
|
||||
}
|
||||
}
|
||||
// Add equip abilities
|
||||
if (this.getAvatar().getExtraAbilityEmbryos().size() > 0) {
|
||||
for (String skill : this.getAvatar().getExtraAbilityEmbryos()) {
|
||||
AbilityEmbryo emb = AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(Utils.abilityHash(skill))
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
AbilityEmbryo emb =
|
||||
AbilityEmbryo.newBuilder()
|
||||
.setAbilityId(++embryoId)
|
||||
.setAbilityNameHash(Utils.abilityHash(skill))
|
||||
.setAbilityOverrideNameHash(GameConstants.DEFAULT_ABILITY_NAME)
|
||||
.build();
|
||||
abilityControlBlock.addAbilityEmbryoList(emb);
|
||||
}
|
||||
}
|
||||
@@ -297,19 +374,35 @@ public class EntityAvatar extends GameEntity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Move this entity to a new position.
|
||||
* Additionally invoke player move event.
|
||||
* Move this entity to a new position. Additionally invoke player move event.
|
||||
*
|
||||
* @param newPosition The new position.
|
||||
* @param rotation The new rotation.
|
||||
*/
|
||||
@Override public void move(Position newPosition, Position rotation) {
|
||||
@Override
|
||||
public void move(Position newPosition, Position rotation) {
|
||||
// Invoke player move event.
|
||||
PlayerMoveEvent event = new PlayerMoveEvent(
|
||||
this.getPlayer(), PlayerMoveEvent.MoveType.PLAYER,
|
||||
this.getPosition(), newPosition
|
||||
); event.call();
|
||||
PlayerMoveEvent event =
|
||||
new PlayerMoveEvent(
|
||||
this.getPlayer(), PlayerMoveEvent.MoveType.PLAYER, this.getPosition(), newPosition);
|
||||
event.call();
|
||||
|
||||
// Set position and rotation.
|
||||
super.move(event.getDestination(), rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAbilityValueUpdate() {
|
||||
super.onAbilityValueUpdate();
|
||||
|
||||
// TODO: Replace with a proper implementation/call.
|
||||
// Check if the condition for 35303 is met.
|
||||
if (this.getGlobalAbilityValues().containsKey("_ABILITY_UziExplode_Count")) {
|
||||
var count = this.getGlobalAbilityValues().get("_ABILITY_UziExplode_Count");
|
||||
if (count == 2f) {
|
||||
this.getGlobalAbilityValues().remove("_ABILITY_UziExplode_Count");
|
||||
this.getPlayer().getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_SKILL, 10006);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,79 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.data.binout.ConfigGadget;
|
||||
import static emu.grasscutter.scripts.constants.EventType.EVENT_SPECIFIC_GADGET_HP_CHANGE;
|
||||
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityGadget;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.event.entity.EntityDamageEvent;
|
||||
import lombok.Getter;
|
||||
|
||||
public abstract class EntityBaseGadget extends GameEntity {
|
||||
@Getter(onMethod_ = @Override)
|
||||
protected final Position position;
|
||||
|
||||
@Getter(onMethod_ = @Override)
|
||||
protected final Position rotation;
|
||||
|
||||
@Getter private final int campId;
|
||||
@Getter private final int campType;
|
||||
|
||||
public EntityBaseGadget(Scene scene) {
|
||||
this(scene, null, null);
|
||||
}
|
||||
|
||||
public EntityBaseGadget(Scene scene, Position position, Position rotation) {
|
||||
this(scene, position, rotation, 0, 0);
|
||||
}
|
||||
|
||||
public EntityBaseGadget(
|
||||
Scene scene, Position position, Position rotation, int campId, int campType) {
|
||||
super(scene);
|
||||
this.position = position != null ? position.clone() : new Position();
|
||||
this.rotation = rotation != null ? rotation.clone() : new Position();
|
||||
this.campId = campId;
|
||||
this.campType = campType;
|
||||
}
|
||||
|
||||
public abstract int getGadgetId();
|
||||
|
||||
@Override
|
||||
public void onDeath(int killerId) {
|
||||
super.onDeath(killerId); // Invoke super class's onDeath() method.
|
||||
public int getEntityTypeId() {
|
||||
return this.getGadgetId();
|
||||
}
|
||||
|
||||
protected void fillFightProps(ConfigGadget configGadget) {
|
||||
@Override
|
||||
public void onDeath(int killerId) {
|
||||
super.onDeath(killerId); // Invoke super class's onDeath() method.
|
||||
|
||||
getScene()
|
||||
.getPlayers()
|
||||
.forEach(
|
||||
p ->
|
||||
p.getQuestManager()
|
||||
.queueEvent(QuestContent.QUEST_CONTENT_DESTROY_GADGET, this.getGadgetId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runLuaCallbacks(EntityDamageEvent event) {
|
||||
super.runLuaCallbacks(event);
|
||||
getScene()
|
||||
.getScriptManager()
|
||||
.callEvent(
|
||||
new ScriptArgs(
|
||||
this.getGroupId(),
|
||||
EVENT_SPECIFIC_GADGET_HP_CHANGE,
|
||||
getConfigId(),
|
||||
getGadgetId())
|
||||
.setSourceEntityId(getId())
|
||||
.setParam3((int) this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP))
|
||||
.setEventSource(Integer.toString(getConfigId())));
|
||||
}
|
||||
|
||||
protected void fillFightProps(ConfigEntityGadget configGadget) {
|
||||
if (configGadget == null || configGadget.getCombat() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityGadget;
|
||||
import emu.grasscutter.data.binout.config.fields.ConfigAbilityData;
|
||||
import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
@@ -17,8 +22,7 @@ import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import emu.grasscutter.utils.helpers.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -28,32 +32,56 @@ public class EntityClientGadget extends EntityBaseGadget {
|
||||
@Getter(onMethod_ = @Override)
|
||||
private int gadgetId;
|
||||
|
||||
@Getter private int campId;
|
||||
@Getter private int campType;
|
||||
@Getter private int ownerEntityId;
|
||||
@Getter private int targetEntityId;
|
||||
@Getter private boolean asyncLoad;
|
||||
|
||||
@Getter private int originalOwnerEntityId;
|
||||
|
||||
@Getter private final GadgetData gadgetData;
|
||||
private ConfigEntityGadget configGadget;
|
||||
|
||||
public EntityClientGadget(Scene scene, Player player, EvtCreateGadgetNotify notify) {
|
||||
super(scene, new Position(notify.getInitPos()), new Position(notify.getInitEulerAngles()));
|
||||
super(
|
||||
scene,
|
||||
new Position(notify.getInitPos()),
|
||||
new Position(notify.getInitEulerAngles()),
|
||||
notify.getCampId(),
|
||||
notify.getCampType());
|
||||
this.owner = player;
|
||||
this.id = notify.getEntityId();
|
||||
this.gadgetId = notify.getConfigId();
|
||||
this.campId = notify.getCampId();
|
||||
this.campType = notify.getCampType();
|
||||
this.ownerEntityId = notify.getPropOwnerEntityId();
|
||||
this.targetEntityId = notify.getTargetEntityId();
|
||||
this.asyncLoad = notify.getIsAsyncLoad();
|
||||
|
||||
this.gadgetData = GameData.getGadgetDataMap().get(gadgetId);
|
||||
if (gadgetData != null && gadgetData.getJsonName() != null) {
|
||||
this.configGadget = GameData.getGadgetConfigData().get(gadgetData.getJsonName());
|
||||
}
|
||||
|
||||
GameEntity owner = scene.getEntityById(this.ownerEntityId);
|
||||
if (owner instanceof EntityClientGadget ownerGadget) {
|
||||
this.originalOwnerEntityId = ownerGadget.getOriginalOwnerEntityId();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.originalOwnerEntityId = this.ownerEntityId;
|
||||
}
|
||||
|
||||
this.initAbilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
if (this.configGadget != null && this.configGadget.getAbilities() != null) {
|
||||
for (var ability : this.configGadget.getAbilities()) {
|
||||
addConfigAbility(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addConfigAbility(ConfigAbilityData abilityData) {
|
||||
var data = GameData.getAbilityData(abilityData.getAbilityName());
|
||||
if (data != null) owner.getAbilityManager().addAbilityToEntity(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,47 +89,60 @@ public class EntityClientGadget extends EntityBaseGadget {
|
||||
super.onDeath(killerId); // Invoke super class's onDeath() method.
|
||||
}
|
||||
|
||||
@Override public Int2FloatMap getFightProperties() {return null;}
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
|
||||
.setBornPos(Vector.newBuilder())
|
||||
.build();
|
||||
EntityAuthorityInfo authority =
|
||||
EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(
|
||||
SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
|
||||
.setBornPos(Vector.newBuilder())
|
||||
.build();
|
||||
|
||||
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
SceneEntityInfo.Builder entityInfo =
|
||||
SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setMotionInfo(
|
||||
MotionInfo.newBuilder()
|
||||
.setPos(getPosition().toProto())
|
||||
.setRot(getRotation().toProto())
|
||||
.setSpeed(Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
|
||||
PropPair pair = PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
|
||||
.build();
|
||||
PropPair pair =
|
||||
PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
|
||||
.build();
|
||||
entityInfo.addPropList(pair);
|
||||
|
||||
ClientGadgetInfoOuterClass.ClientGadgetInfo clientGadget = ClientGadgetInfoOuterClass.ClientGadgetInfo.newBuilder()
|
||||
.setCampId(this.getCampId())
|
||||
.setCampType(this.getCampType())
|
||||
.setOwnerEntityId(this.getOwnerEntityId())
|
||||
.setTargetEntityId(this.getTargetEntityId())
|
||||
.setAsyncLoad(this.isAsyncLoad())
|
||||
.build();
|
||||
ClientGadgetInfoOuterClass.ClientGadgetInfo clientGadget =
|
||||
ClientGadgetInfoOuterClass.ClientGadgetInfo.newBuilder()
|
||||
.setCampId(this.getCampId())
|
||||
.setCampType(this.getCampType())
|
||||
.setOwnerEntityId(this.getOwnerEntityId())
|
||||
.setTargetEntityId(this.getTargetEntityId())
|
||||
.setAsyncLoad(this.isAsyncLoad())
|
||||
.build();
|
||||
|
||||
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(this.getGadgetId())
|
||||
.setOwnerEntityId(this.getOwnerEntityId())
|
||||
.setIsEnableInteract(true)
|
||||
.setClientGadget(clientGadget)
|
||||
.setPropOwnerEntityId(this.getOwnerEntityId())
|
||||
.setAuthorityPeerId(this.getOwner().getPeerId());
|
||||
SceneGadgetInfo.Builder gadgetInfo =
|
||||
SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(this.getGadgetId())
|
||||
.setOwnerEntityId(this.getOwnerEntityId())
|
||||
.setIsEnableInteract(true)
|
||||
.setClientGadget(clientGadget)
|
||||
.setPropOwnerEntityId(this.getOwnerEntityId())
|
||||
.setAuthorityPeerId(this.getOwner().getPeerId());
|
||||
|
||||
entityInfo.setGadget(gadgetInfo);
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.ConfigGadget;
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityGadget;
|
||||
import emu.grasscutter.data.binout.config.fields.ConfigAbilityData;
|
||||
import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.game.entity.gadget.*;
|
||||
import emu.grasscutter.game.entity.gadget.platform.BaseRoute;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.SceneGroupInstance;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
||||
@@ -15,42 +20,61 @@ import emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData;
|
||||
import emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo;
|
||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
|
||||
import emu.grasscutter.net.proto.PlatformInfoOuterClass;
|
||||
import emu.grasscutter.net.proto.PropPairOuterClass.PropPair;
|
||||
import emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType;
|
||||
import emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import emu.grasscutter.net.proto.VisionTypeOuterClass;
|
||||
import emu.grasscutter.scripts.EntityControllerScriptManager;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetStateNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import emu.grasscutter.server.packet.send.PacketPlatformStartRouteNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketPlatformStopRouteNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneTimeNotify;
|
||||
import emu.grasscutter.utils.helpers.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ToString(callSuper = true)
|
||||
public class EntityGadget extends EntityBaseGadget {
|
||||
@Getter private final GadgetData gadgetData;
|
||||
@Getter(onMethod_ = @Override) @Setter
|
||||
|
||||
@Getter(onMethod_ = @Override)
|
||||
@Setter
|
||||
private int gadgetId;
|
||||
|
||||
@Getter @Setter private int state;
|
||||
@Getter private final Position bornPos;
|
||||
@Getter private final Position bornRot;
|
||||
@Getter @Setter private GameEntity owner = null;
|
||||
@Getter @Setter private List<GameEntity> children = new ArrayList<>();
|
||||
|
||||
@Getter private int state;
|
||||
@Getter @Setter private int pointType;
|
||||
@Getter private GadgetContent content;
|
||||
|
||||
@Getter(onMethod_ = @Override, lazy = true)
|
||||
private final Int2FloatMap fightProperties = new Int2FloatOpenHashMap();
|
||||
|
||||
@Getter @Setter private SceneGadget metaGadget;
|
||||
@Nullable @Getter
|
||||
private ConfigGadget configGadget;
|
||||
@Nullable @Getter ConfigEntityGadget configGadget;
|
||||
@Getter @Setter private BaseRoute routeConfig;
|
||||
|
||||
@Getter @Setter private int stopValue = 0; // Controller related, inited to zero
|
||||
@Getter @Setter private int startValue = 0; // Controller related, inited to zero
|
||||
@Getter @Setter private int ticksSinceChange;
|
||||
|
||||
@Getter private boolean interactEnabled = true;
|
||||
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos) {
|
||||
this(scene, gadgetId, pos, null, null);
|
||||
@@ -60,20 +84,91 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
this(scene, gadgetId, pos, rot, null);
|
||||
}
|
||||
|
||||
public EntityGadget(Scene scene, int gadgetId, Position pos, Position rot, GadgetContent content) {
|
||||
super(scene, pos, rot);
|
||||
public EntityGadget(
|
||||
Scene scene, int gadgetId, Position pos, Position rot, int campId, int campType) {
|
||||
this(scene, gadgetId, pos, rot, null, campId, campType);
|
||||
}
|
||||
|
||||
public EntityGadget(
|
||||
Scene scene, int gadgetId, Position pos, Position rot, GadgetContent content) {
|
||||
this(scene, gadgetId, pos, rot, content, 0, 0);
|
||||
}
|
||||
|
||||
public EntityGadget(
|
||||
Scene scene,
|
||||
int gadgetId,
|
||||
Position pos,
|
||||
Position rot,
|
||||
GadgetContent content,
|
||||
int campId,
|
||||
int campType) {
|
||||
super(scene, pos, rot, campId, campType);
|
||||
|
||||
this.gadgetData = GameData.getGadgetDataMap().get(gadgetId);
|
||||
this.configGadget = Optional.ofNullable(this.gadgetData).map(GadgetData::getJsonName).map(GameData.getGadgetConfigData()::get).orElse(null);
|
||||
if (gadgetData != null && gadgetData.getJsonName() != null) {
|
||||
this.configGadget = GameData.getGadgetConfigData().get(gadgetData.getJsonName());
|
||||
}
|
||||
|
||||
this.id = this.getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.gadgetId = gadgetId;
|
||||
this.content = content;
|
||||
fillFightProps(configGadget);
|
||||
this.bornPos = this.getPosition().clone();
|
||||
this.bornRot = this.getRotation().clone();
|
||||
this.fillFightProps(configGadget);
|
||||
|
||||
if (GameData.getGadgetMappingMap().containsKey(gadgetId)) {
|
||||
var controllerName = GameData.getGadgetMappingMap().get(gadgetId).getServerController();
|
||||
this.setEntityController(EntityControllerScriptManager.getGadgetController(controllerName));
|
||||
if (this.getEntityController() == null) {
|
||||
Grasscutter.getLogger().warn("Gadget controller {} not found.", controllerName);
|
||||
}
|
||||
}
|
||||
|
||||
this.initAbilities(); // TODO: move this
|
||||
}
|
||||
|
||||
private void addConfigAbility(ConfigAbilityData abilityData) {
|
||||
var data = GameData.getAbilityData(abilityData.getAbilityName());
|
||||
if (data != null)
|
||||
this.getScene().getWorld().getHost().getAbilityManager().addAbilityToEntity(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// TODO: handle pre-dynamic, static and dynamic here
|
||||
if (this.configGadget != null && this.configGadget.getAbilities() != null) {
|
||||
for (var ability : this.configGadget.getAbilities()) {
|
||||
this.addConfigAbility(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setInteractEnabled(boolean enable) {
|
||||
this.interactEnabled = enable;
|
||||
this.getScene()
|
||||
.broadcastPacket(new PacketGadgetStateNotify(this, this.getState())); // Update the interact
|
||||
}
|
||||
|
||||
public void setState(int state) {
|
||||
this.state = state;
|
||||
// Cache the gadget state
|
||||
if (metaGadget != null && metaGadget.group != null) {
|
||||
var instance = getScene().getScriptManager().getCachedGroupInstanceById(metaGadget.group.id);
|
||||
if (instance != null) instance.cacheGadgetState(metaGadget, state);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateState(int state) {
|
||||
if (state == this.getState()) return; // Don't triggers events
|
||||
|
||||
this.setState(state);
|
||||
ticksSinceChange = getScene().getSceneTimeSeconds();
|
||||
this.getScene().broadcastPacket(new PacketGadgetStateNotify(this, state));
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_GADGET_STATE_CHANGE, new ScriptArgs(state, this.getConfigId()));
|
||||
getScene()
|
||||
.getScriptManager()
|
||||
.callEvent(
|
||||
new ScriptArgs(
|
||||
this.getGroupId(), EventType.EVENT_GADGET_STATE_CHANGE, state, this.getConfigId()));
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true) // Dont use!
|
||||
@@ -83,23 +178,28 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
|
||||
// TODO refactor
|
||||
public void buildContent() {
|
||||
if (this.getContent() != null || this.getGadgetData() == null || this.getGadgetData().getType() == null) {
|
||||
if (this.getContent() != null
|
||||
|| this.getGadgetData() == null
|
||||
|| this.getGadgetData().getType() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.content = switch (this.getGadgetData().getType()) {
|
||||
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);
|
||||
case Gadget -> new GadgetObject(this);
|
||||
default -> null;
|
||||
};
|
||||
this.content =
|
||||
switch (this.getGadgetData().getType()) {
|
||||
case GatherPoint -> new GadgetGatherPoint(this);
|
||||
case GatherObject -> new GadgetGatherObject(this);
|
||||
case Worktop, SealGadget -> new GadgetWorktop(this);
|
||||
case RewardStatue -> new GadgetRewardStatue(this);
|
||||
case Chest -> new GadgetChest(this);
|
||||
case Gadget -> new GadgetObject(this);
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteract(Player player, GadgetInteractReq interactReq) {
|
||||
if (!this.interactEnabled) return;
|
||||
|
||||
if (this.getContent() == null) {
|
||||
return;
|
||||
}
|
||||
@@ -114,7 +214,19 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
// Lua event
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_GADGET_CREATE, new ScriptArgs(this.getConfigId()));
|
||||
getScene()
|
||||
.getScriptManager()
|
||||
.callEvent(
|
||||
new ScriptArgs(this.getGroupId(), EventType.EVENT_GADGET_CREATE, this.getConfigId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved() {
|
||||
super.onRemoved();
|
||||
if (!children.isEmpty()) {
|
||||
getScene().removeEntities(children, VisionTypeOuterClass.VisionType.VISION_TYPE_REMOVE);
|
||||
children.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,56 +239,119 @@ public class EntityGadget extends EntityBaseGadget {
|
||||
if (getScene().getChallenge() != null) {
|
||||
getScene().getChallenge().onGadgetDeath(this);
|
||||
}
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_GADGET_DIE, new ScriptArgs(this.getConfigId()));
|
||||
getScene()
|
||||
.getScriptManager()
|
||||
.callEvent(
|
||||
new ScriptArgs(this.getGroupId(), EventType.EVENT_ANY_GADGET_DIE, this.getConfigId()));
|
||||
|
||||
SceneGroupInstance groupInstance =
|
||||
getScene().getScriptManager().getCachedGroupInstanceById(this.getGroupId());
|
||||
if (groupInstance != null && metaGadget != null)
|
||||
groupInstance.getDeadEntities().add(metaGadget.config_id);
|
||||
}
|
||||
|
||||
public boolean startPlatform() {
|
||||
if (routeConfig == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (routeConfig.isStarted()) {
|
||||
return true;
|
||||
}
|
||||
getScene().broadcastPacket(new PacketSceneTimeNotify(getScene()));
|
||||
routeConfig.startRoute(getScene());
|
||||
getScene().broadcastPacket(new PacketPlatformStartRouteNotify(this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean stopPlatform() {
|
||||
if (routeConfig == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!routeConfig.isStarted()) {
|
||||
return true;
|
||||
}
|
||||
routeConfig.stopRoute(getScene());
|
||||
getScene().broadcastPacket(new PacketPlatformStopRouteNotify(this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
|
||||
.setBornPos(Vector.newBuilder())
|
||||
.build();
|
||||
EntityAuthorityInfo authority =
|
||||
EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(
|
||||
SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(bornPos.toProto()))
|
||||
.setBornPos(bornPos.toProto())
|
||||
.build();
|
||||
|
||||
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
SceneEntityInfo.Builder entityInfo =
|
||||
SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setMotionInfo(
|
||||
MotionInfo.newBuilder()
|
||||
.setPos(getPosition().toProto())
|
||||
.setRot(getRotation().toProto())
|
||||
.setSpeed(Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
|
||||
PropPair pair = PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
|
||||
.build();
|
||||
PropPair pair =
|
||||
PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
|
||||
.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
|
||||
// We do not use the getter to null check because the getter will create a fight prop map if it
|
||||
// is null
|
||||
if (this.fightProperties != null) {
|
||||
addAllFightPropsToEntityInfo(entityInfo);
|
||||
}
|
||||
|
||||
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(this.getGadgetId())
|
||||
.setGroupId(this.getGroupId())
|
||||
.setConfigId(this.getConfigId())
|
||||
.setGadgetState(this.getState())
|
||||
.setIsEnableInteract(true)
|
||||
.setAuthorityPeerId(this.getScene().getWorld().getHostPeerId());
|
||||
var gadgetInfo =
|
||||
SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(this.getGadgetId())
|
||||
.setGroupId(this.getGroupId())
|
||||
.setConfigId(this.getConfigId())
|
||||
.setGadgetState(this.getState())
|
||||
.setIsEnableInteract(this.interactEnabled)
|
||||
.setAuthorityPeerId(this.getScene().getWorld().getHostPeerId());
|
||||
|
||||
if (this.metaGadget != null) {
|
||||
gadgetInfo.setDraftId(this.metaGadget.draft_id);
|
||||
}
|
||||
|
||||
if (owner != null) {
|
||||
gadgetInfo.setOwnerEntityId(owner.getId());
|
||||
}
|
||||
|
||||
if (this.getContent() != null) {
|
||||
this.getContent().onBuildProto(gadgetInfo);
|
||||
}
|
||||
|
||||
if (routeConfig != null) {
|
||||
gadgetInfo.setPlatform(getPlatformInfo());
|
||||
}
|
||||
|
||||
entityInfo.setGadget(gadgetInfo);
|
||||
|
||||
return entityInfo.build();
|
||||
}
|
||||
|
||||
public PlatformInfoOuterClass.PlatformInfo.Builder getPlatformInfo() {
|
||||
if (routeConfig != null) {
|
||||
return routeConfig.toProto();
|
||||
}
|
||||
|
||||
return PlatformInfoOuterClass.PlatformInfo.newBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
@@ -23,8 +24,7 @@ import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import emu.grasscutter.utils.helpers.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -37,13 +37,17 @@ public class EntityItem extends EntityBaseGadget {
|
||||
this(scene, player, itemData, pos, count, true);
|
||||
}
|
||||
|
||||
// In official game, some drop items are shared to all players, and some other items are independent to all players
|
||||
// For example, if you killed a monster in MP mode, all players could get drops but rarity and number of them are different
|
||||
// In official game, some drop items are shared to all players, and some other items are
|
||||
// independent to all players
|
||||
// For example, if you killed a monster in MP mode, all players could get drops but rarity and
|
||||
// number of them are different
|
||||
// but if you broke regional mine, when someone picked up the drop then it disappeared
|
||||
public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) {
|
||||
public EntityItem(
|
||||
Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) {
|
||||
super(scene, pos, null);
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.guid = player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
|
||||
this.guid =
|
||||
player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();
|
||||
this.item = new GameItem(itemData, count);
|
||||
this.share = share;
|
||||
}
|
||||
@@ -61,7 +65,10 @@ public class EntityItem extends EntityBaseGadget {
|
||||
return this.getItemData().getGadgetId();
|
||||
}
|
||||
|
||||
@Override public Int2FloatMap getFightProperties() {return null;}
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInteract(Player player, GadgetInteractReq interactReq) {
|
||||
@@ -82,44 +89,61 @@ public class EntityItem extends EntityBaseGadget {
|
||||
if (!this.isShare()) { // not shared drop
|
||||
player.sendPacket(new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM));
|
||||
} else {
|
||||
this.getScene().broadcastPacket(new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM));
|
||||
this.getScene()
|
||||
.broadcastPacket(
|
||||
new PacketGadgetInteractRsp(this, InteractType.INTERACT_TYPE_PICK_ITEM));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
|
||||
.setBornPos(Vector.newBuilder())
|
||||
.build();
|
||||
EntityAuthorityInfo authority =
|
||||
EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(
|
||||
SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(Vector.newBuilder()))
|
||||
.setBornPos(Vector.newBuilder())
|
||||
.build();
|
||||
|
||||
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
SceneEntityInfo.Builder entityInfo =
|
||||
SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setMotionInfo(
|
||||
MotionInfo.newBuilder()
|
||||
.setPos(getPosition().toProto())
|
||||
.setRot(getRotation().toProto())
|
||||
.setSpeed(Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
|
||||
PropPair pair = PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
|
||||
.build();
|
||||
PropPair pair =
|
||||
PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 1))
|
||||
.build();
|
||||
entityInfo.addPropList(pair);
|
||||
|
||||
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(this.getItemData().getGadgetId())
|
||||
.setTrifleItem(this.getItem().toProto())
|
||||
.setBornType(GadgetBornType.GADGET_BORN_TYPE_IN_AIR)
|
||||
.setAuthorityPeerId(this.getWorld().getHostPeerId())
|
||||
.setIsEnableInteract(true);
|
||||
SceneGadgetInfo.Builder gadgetInfo =
|
||||
SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(this.getItemData().getGadgetId())
|
||||
.setTrifleItem(this.getItem().toProto())
|
||||
.setBornType(GadgetBornType.GADGET_BORN_TYPE_IN_AIR)
|
||||
.setAuthorityPeerId(this.getWorld().getHostPeerId())
|
||||
.setIsEnableInteract(true);
|
||||
|
||||
entityInfo.setGadget(gadgetInfo);
|
||||
|
||||
return entityInfo.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'initAbilities'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.AbilityData;
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityMonster;
|
||||
import emu.grasscutter.data.common.PropGrowCurve;
|
||||
import emu.grasscutter.data.excels.EnvAnimalGatherConfigData;
|
||||
import emu.grasscutter.data.excels.MonsterCurveData;
|
||||
import emu.grasscutter.data.excels.MonsterData;
|
||||
import emu.grasscutter.data.excels.monster.MonsterCurveData;
|
||||
import emu.grasscutter.data.excels.monster.MonsterData;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||
import emu.grasscutter.game.props.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.data.excels.MonsterSpecialNameData;
|
||||
import emu.grasscutter.game.world.SceneGroupInstance;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo;
|
||||
@@ -29,15 +28,22 @@ import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import emu.grasscutter.net.proto.SceneMonsterInfoOuterClass.SceneMonsterInfo;
|
||||
import emu.grasscutter.net.proto.SceneWeaponInfoOuterClass.SceneWeaponInfo;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.SceneMonster;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import emu.grasscutter.server.event.entity.EntityDamageEvent;
|
||||
import emu.grasscutter.utils.helpers.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static emu.grasscutter.scripts.constants.EventType.EVENT_SPECIFIC_MONSTER_HP_CHANGE;
|
||||
|
||||
public class EntityMonster extends GameEntity {
|
||||
@Getter private final MonsterData monsterData;
|
||||
@Getter(onMethod_ = @Override)
|
||||
private final Int2FloatOpenHashMap fightProperties;
|
||||
|
||||
@@ -45,12 +51,17 @@ public class EntityMonster extends GameEntity {
|
||||
private final Position position;
|
||||
@Getter(onMethod_ = @Override)
|
||||
private final Position rotation;
|
||||
@Getter private final MonsterData monsterData;
|
||||
@Getter private final ConfigEntityMonster configEntityMonster;
|
||||
@Getter private final Position bornPos;
|
||||
@Getter private final int level;
|
||||
private int weaponEntityId;
|
||||
@Getter private EntityWeapon weaponEntity;
|
||||
@Getter @Setter private int poseId;
|
||||
@Getter @Setter private int aiId = -1;
|
||||
|
||||
@Getter private List<Player> playerOnBattle;
|
||||
@Nullable @Getter @Setter private SceneMonster metaMonster;
|
||||
|
||||
public EntityMonster(Scene scene, MonsterData monsterData, Position pos, int level) {
|
||||
super(scene);
|
||||
this.id = getWorld().getNextEntityId(EntityIdType.MONSTER);
|
||||
@@ -60,13 +71,107 @@ public class EntityMonster extends GameEntity {
|
||||
this.rotation = new Position();
|
||||
this.bornPos = getPosition().clone();
|
||||
this.level = level;
|
||||
this.playerOnBattle = new ArrayList<>();
|
||||
|
||||
if(GameData.getMonsterMappingMap().containsKey(getMonsterId())) {
|
||||
this.configEntityMonster = GameData.getMonsterConfigData().get(GameData.getMonsterMappingMap().get(getMonsterId()).getMonsterJson());
|
||||
} else {
|
||||
this.configEntityMonster = null;
|
||||
}
|
||||
|
||||
// Monster weapon
|
||||
if (getMonsterWeaponId() > 0) {
|
||||
this.weaponEntityId = getWorld().getNextEntityId(EntityIdType.WEAPON);
|
||||
this.weaponEntity = new EntityWeapon(scene, getMonsterWeaponId());
|
||||
scene.getWeaponEntities().put(this.weaponEntity.getId(), this.weaponEntity);
|
||||
//this.weaponEntityId = getWorld().getNextEntityId(EntityIdType.WEAPON);
|
||||
}
|
||||
|
||||
this.recalcStats();
|
||||
|
||||
initAbilities();
|
||||
}
|
||||
|
||||
private void addConfigAbility(String name){
|
||||
AbilityData data = GameData.getAbilityData(name);
|
||||
if(data != null)
|
||||
getScene().getWorld().getHost().getAbilityManager().addAbilityToEntity(
|
||||
this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
if(configEntityMonster != null) {
|
||||
// Affix abilities
|
||||
var optionalGroup = getScene().getLoadedGroups().stream()
|
||||
.filter(g -> g.id == this.getGroupId())
|
||||
.findAny();
|
||||
List<Integer> affixes = null;
|
||||
if (optionalGroup.isPresent()) {
|
||||
var group = optionalGroup.get();
|
||||
|
||||
SceneMonster monster = group.monsters.get(getConfigId());
|
||||
if(monster != null) affixes = monster.affix;
|
||||
}
|
||||
|
||||
if (affixes != null) {
|
||||
for(var affixId : affixes) {
|
||||
var affix = GameData.getMonsterAffixDataMap().get(affixId.intValue());
|
||||
if (!affix.isPreAdd()) continue;
|
||||
|
||||
//Add the ability
|
||||
for(var name : affix.getAbilityName()) {
|
||||
this.addConfigAbility(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Research if any monster is non humanoid
|
||||
for(var ability : GameData.getConfigGlobalCombat().getDefaultAbilities().getNonHumanoidMoveAbilities()) {
|
||||
this.addConfigAbility(ability);
|
||||
}
|
||||
|
||||
if (configEntityMonster.getAbilities() != null)
|
||||
for (var configAbilityData : configEntityMonster.getAbilities()) {
|
||||
this.addConfigAbility(configAbilityData.abilityName);
|
||||
}
|
||||
|
||||
if (optionalGroup.isPresent()) {
|
||||
var group = optionalGroup.get();
|
||||
SceneMonster monster = group.monsters.get(getConfigId());
|
||||
if(monster != null && monster.isElite) {
|
||||
addConfigAbility(GameData.getConfigGlobalCombat().getDefaultAbilities().getMonterEliteAbilityName());
|
||||
}
|
||||
}
|
||||
|
||||
if (affixes != null) {
|
||||
for (var affixId : affixes) {
|
||||
var affix = GameData.getMonsterAffixDataMap().get(affixId.intValue());
|
||||
if(affix.isPreAdd()) continue;
|
||||
|
||||
//Add the ability
|
||||
for(var name : affix.getAbilityName()) {
|
||||
this.addConfigAbility(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var levelEntityConfig = getScene().getSceneData().getLevelEntityConfig();
|
||||
var config = GameData.getConfigLevelEntityDataMap().get(levelEntityConfig);
|
||||
if (config == null){
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.getMonsterAbilities() != null) {
|
||||
for (var monsterAbility : config.getMonsterAbilities()) {
|
||||
addConfigAbility(monsterAbility.abilityName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityTypeId() {
|
||||
return getMonsterId();
|
||||
}
|
||||
|
||||
public int getMonsterWeaponId() {
|
||||
@@ -98,16 +203,16 @@ public class EntityMonster extends GameEntity {
|
||||
@Override
|
||||
public void onCreate() {
|
||||
// Lua event
|
||||
getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_LIVE, new ScriptArgs(this.getConfigId()));
|
||||
getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroupId(), EventType.EVENT_ANY_MONSTER_LIVE, this.getConfigId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage(float amount, int killerId) {
|
||||
public void damage(float amount, int killerId, ElementType attackType) {
|
||||
// Get HP before damage.
|
||||
float hpBeforeDamage = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
|
||||
|
||||
// Apply damage.
|
||||
super.damage(amount, killerId);
|
||||
super.damage(amount, killerId, attackType);
|
||||
|
||||
// Get HP after damage.
|
||||
float hpAfterDamage = this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
|
||||
@@ -118,6 +223,15 @@ public class EntityMonster extends GameEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runLuaCallbacks(EntityDamageEvent event) {
|
||||
super.runLuaCallbacks(event);
|
||||
getScene().getScriptManager().callEvent(new ScriptArgs(this.getGroupId(), EVENT_SPECIFIC_MONSTER_HP_CHANGE, getConfigId(), monsterData.getId())
|
||||
.setSourceEntityId(getId())
|
||||
.setParam3((int) this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP))
|
||||
.setEventSource(Integer.toString(getConfigId())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeath(int killerId) {
|
||||
super.onDeath(killerId); // Invoke super class's onDeath() method.
|
||||
@@ -134,11 +248,26 @@ public class EntityMonster extends GameEntity {
|
||||
Optional.ofNullable(scriptManager.getScriptMonsterSpawnService()).ifPresent(s -> s.onMonsterDead(this));
|
||||
|
||||
// prevent spawn monster after success
|
||||
if (challenge.map(c -> c.inProgress()).orElse(true))
|
||||
scriptManager.callEvent(EventType.EVENT_ANY_MONSTER_DIE, new ScriptArgs().setParam1(this.getConfigId()));
|
||||
/*if (challenge.map(c -> c.inProgress()).orElse(true)) {
|
||||
scriptManager.callEvent(new ScriptArgs(EventType.EVENT_ANY_MONSTER_DIE, this.getConfigId()).setGroupId(this.getGroupId()));
|
||||
} else if (getScene().getChallenge() == null) {
|
||||
}*/
|
||||
scriptManager.callEvent(new ScriptArgs(this.getGroupId(), EventType.EVENT_ANY_MONSTER_DIE, this.getConfigId()));
|
||||
}
|
||||
// Battle Pass trigger
|
||||
scene.getPlayers().forEach(p -> p.getBattlePassManager().triggerMission(WatcherTriggerType.TRIGGER_MONSTER_DIE, this.getMonsterId(), 1));
|
||||
|
||||
scene.getPlayers().forEach(p -> p.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_MONSTER_DIE, this.getMonsterId()));
|
||||
scene.getPlayers().forEach(p -> p.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_KILL_MONSTER, this.getMonsterId()));
|
||||
scene.getPlayers().forEach(p -> p.getQuestManager().queueEvent(QuestContent.QUEST_CONTENT_CLEAR_GROUP_MONSTER, this.getGroupId()));
|
||||
|
||||
SceneGroupInstance groupInstance = scene.getScriptManager().getGroupInstanceById(this.getGroupId());
|
||||
if(groupInstance != null && metaMonster != null)
|
||||
groupInstance.getDeadEntities().add(metaMonster.config_id);
|
||||
|
||||
scene.triggerDungeonEvent(DungeonPassConditionType.DUNGEON_COND_KILL_GROUP_MONSTER, this.getGroupId());
|
||||
scene.triggerDungeonEvent(DungeonPassConditionType.DUNGEON_COND_KILL_TYPE_MONSTER, this.getMonsterData().getType().getValue());
|
||||
scene.triggerDungeonEvent(DungeonPassConditionType.DUNGEON_COND_KILL_MONSTER, this.getMonsterId());
|
||||
}
|
||||
|
||||
public void recalcStats() {
|
||||
@@ -173,54 +302,63 @@ public class EntityMonster extends GameEntity {
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
var data = this.getMonsterData();
|
||||
|
||||
var authority = EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(this.getBornPos().toProto()))
|
||||
.setBornPos(this.getBornPos().toProto())
|
||||
.build();
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfo.newBuilder()
|
||||
.setIsAiOpen(true)
|
||||
.setBornPos(this.getBornPos().toProto()))
|
||||
.setBornPos(this.getBornPos().toProto())
|
||||
.build();
|
||||
|
||||
var entityInfo = SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_MONSTER)
|
||||
.setMotionInfo(this.getMotionInfo())
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(this.getLifeState().getValue());
|
||||
.setEntityId(this.getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_MONSTER)
|
||||
.setMotionInfo(this.getMotionInfo())
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(this.getLifeState().getValue());
|
||||
|
||||
this.addAllFightPropsToEntityInfo(entityInfo);
|
||||
|
||||
entityInfo.addPropList(PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, getLevel()))
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, this.getLevel()))
|
||||
.build());
|
||||
|
||||
var monsterInfo = SceneMonsterInfo.newBuilder()
|
||||
.setMonsterId(getMonsterId())
|
||||
.setGroupId(this.getGroupId())
|
||||
.setConfigId(this.getConfigId())
|
||||
.addAllAffixList(getMonsterData().getAffix())
|
||||
.setAuthorityPeerId(getWorld().getHostPeerId())
|
||||
.setPoseId(this.getPoseId())
|
||||
.setBlockId(getScene().getId())
|
||||
.setBornType(MonsterBornType.MONSTER_BORN_TYPE_DEFAULT);
|
||||
.setMonsterId(getMonsterId())
|
||||
.setGroupId(this.getGroupId())
|
||||
.setConfigId(this.getConfigId())
|
||||
.addAllAffixList(data.getAffix())
|
||||
.setAuthorityPeerId(this.getWorld().getHostPeerId())
|
||||
.setPoseId(this.getPoseId())
|
||||
.setBlockId(this.getScene().getId())
|
||||
.setBornType(MonsterBornType.MONSTER_BORN_TYPE_DEFAULT);
|
||||
|
||||
if (getMonsterData().getDescribeData() != null) {
|
||||
monsterInfo.setTitleId(getMonsterData().getDescribeData().getTitleId())
|
||||
.setSpecialNameId(getMonsterData().getSpecialNameId());
|
||||
if (this.metaMonster != null) {
|
||||
if (this.metaMonster.special_name_id != 0) {
|
||||
monsterInfo.setTitleId(this.metaMonster.title_id)
|
||||
.setSpecialNameId(this.metaMonster.special_name_id);
|
||||
} else if (data.getDescribeData() != null) {
|
||||
monsterInfo.setTitleId(data.getDescribeData().getTitleId())
|
||||
.setSpecialNameId(data.getSpecialNameId());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getMonsterWeaponId() > 0) {
|
||||
SceneWeaponInfo weaponInfo = SceneWeaponInfo.newBuilder()
|
||||
.setEntityId(this.weaponEntityId)
|
||||
.setGadgetId(this.getMonsterWeaponId())
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.build();
|
||||
.setEntityId(this.getWeaponEntity() != null ? this.getWeaponEntity().getId() : 0)
|
||||
.setGadgetId(this.getMonsterWeaponId())
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.build();
|
||||
|
||||
monsterInfo.addWeaponList(weaponInfo);
|
||||
}
|
||||
if (this.aiId!=-1) {
|
||||
if (this.aiId != -1) {
|
||||
monsterInfo.setAiConfigId(aiId);
|
||||
}
|
||||
|
||||
@@ -228,4 +366,4 @@ public class EntityMonster extends GameEntity {
|
||||
|
||||
return entityInfo.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.*;
|
||||
import emu.grasscutter.scripts.data.SceneNPC;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
public class EntityNPC extends GameEntity{
|
||||
public class EntityNPC extends GameEntity {
|
||||
@Getter(onMethod_ = @Override)
|
||||
private final Position position;
|
||||
|
||||
@Getter(onMethod_ = @Override)
|
||||
private final Position rotation;
|
||||
|
||||
private final SceneNPC metaNpc;
|
||||
@Getter private final int suiteId;
|
||||
|
||||
@@ -26,41 +28,61 @@ public class EntityNPC extends GameEntity{
|
||||
this.position = metaNPC.pos.clone();
|
||||
this.rotation = metaNPC.rot.clone();
|
||||
this.metaNpc = metaNPC;
|
||||
|
||||
}
|
||||
|
||||
@Override public Int2FloatMap getFightProperties() {return null;}
|
||||
@Override
|
||||
public int getEntityTypeId() {
|
||||
return this.metaNpc.npc_id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfoOuterClass.SceneEntityInfo toProto() {
|
||||
|
||||
EntityAuthorityInfoOuterClass.EntityAuthorityInfo authority = EntityAuthorityInfoOuterClass.EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfoOuterClass.SceneEntityAiInfo.newBuilder()
|
||||
.setIsAiOpen(true)
|
||||
.setBornPos(getPosition().toProto()))
|
||||
.setBornPos(getPosition().toProto())
|
||||
.build();
|
||||
EntityAuthorityInfoOuterClass.EntityAuthorityInfo authority =
|
||||
EntityAuthorityInfoOuterClass.EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(
|
||||
EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(
|
||||
SceneEntityAiInfoOuterClass.SceneEntityAiInfo.newBuilder()
|
||||
.setIsAiOpen(true)
|
||||
.setBornPos(getPosition().toProto()))
|
||||
.setBornPos(getPosition().toProto())
|
||||
.build();
|
||||
|
||||
SceneEntityInfoOuterClass.SceneEntityInfo.Builder entityInfo = SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_NPC)
|
||||
.setMotionInfo(MotionInfoOuterClass.MotionInfo.newBuilder()
|
||||
.setPos(getPosition().toProto())
|
||||
.setRot(getRotation().toProto())
|
||||
.setSpeed(VectorOuterClass.Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setEntityClientData(EntityClientDataOuterClass.EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
SceneEntityInfoOuterClass.SceneEntityInfo.Builder entityInfo =
|
||||
SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_NPC)
|
||||
.setMotionInfo(
|
||||
MotionInfoOuterClass.MotionInfo.newBuilder()
|
||||
.setPos(getPosition().toProto())
|
||||
.setRot(getRotation().toProto())
|
||||
.setSpeed(VectorOuterClass.Vector.newBuilder()))
|
||||
.addAnimatorParaList(
|
||||
AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair
|
||||
.newBuilder())
|
||||
.setEntityClientData(EntityClientDataOuterClass.EntityClientData.newBuilder())
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
|
||||
|
||||
entityInfo.setNpc(SceneNpcInfoOuterClass.SceneNpcInfo.newBuilder()
|
||||
entityInfo.setNpc(
|
||||
SceneNpcInfoOuterClass.SceneNpcInfo.newBuilder()
|
||||
.setNpcId(metaNpc.npc_id)
|
||||
.setBlockId(getBlockId())
|
||||
.build());
|
||||
.build());
|
||||
|
||||
return entityInfo.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'initAbilities'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,52 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass;
|
||||
import emu.grasscutter.scripts.data.SceneRegion;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class EntityRegion extends GameEntity{
|
||||
public class EntityRegion extends GameEntity {
|
||||
private final Position position;
|
||||
private boolean hasNewEntities;
|
||||
private boolean entityLeave;
|
||||
private final Set<Integer> entities; // Ids of entities inside this region
|
||||
private final SceneRegion metaRegion;
|
||||
private boolean entityEnter;
|
||||
private boolean entityLeave;
|
||||
|
||||
public EntityRegion(Scene scene, SceneRegion region) {
|
||||
super(scene);
|
||||
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.REGION);
|
||||
setGroupId(region.group.id);
|
||||
setBlockId(region.group.block_id);
|
||||
setConfigId(region.config_id);
|
||||
this.setGroupId(region.group.id);
|
||||
this.setBlockId(region.group.block_id);
|
||||
this.setConfigId(region.config_id);
|
||||
this.position = region.pos.clone();
|
||||
this.entities = ConcurrentHashMap.newKeySet();
|
||||
this.metaRegion = region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityTypeId() {
|
||||
return this.metaRegion.config_id;
|
||||
}
|
||||
|
||||
public void resetNewEntities() {
|
||||
this.entityEnter = false;
|
||||
this.entityLeave = false;
|
||||
}
|
||||
|
||||
public void addEntity(GameEntity entity) {
|
||||
if (this.getEntities().contains(entity.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.getEntities().add(entity.getId());
|
||||
this.hasNewEntities = true;
|
||||
}
|
||||
|
||||
public boolean hasNewEntities() {
|
||||
return hasNewEntities;
|
||||
}
|
||||
|
||||
public void resetNewEntities() {
|
||||
hasNewEntities = false;
|
||||
this.entityEnter = true;
|
||||
}
|
||||
|
||||
public void removeEntity(int entityId) {
|
||||
@@ -52,26 +55,45 @@ public class EntityRegion extends GameEntity{
|
||||
}
|
||||
|
||||
public void removeEntity(GameEntity entity) {
|
||||
this.getEntities().remove(entity.getId());
|
||||
this.entityLeave = true;
|
||||
this.removeEntity(entity.getId());
|
||||
}
|
||||
public boolean entityLeave() {return this.entityLeave;}
|
||||
public void resetEntityLeave() {this.entityLeave = false;}
|
||||
@Override public Int2FloatMap getFightProperties() {return null;}
|
||||
|
||||
@Override public Position getPosition() {return position;}
|
||||
public boolean entityHasEntered() {
|
||||
return this.entityEnter;
|
||||
}
|
||||
|
||||
@Override public Position getRotation() {return null;}
|
||||
public boolean entityHasLeft() {
|
||||
return this.entityLeave;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfoOuterClass.SceneEntityInfo toProto() {
|
||||
/**
|
||||
* The Region Entity would not be sent to client.
|
||||
*/
|
||||
/** The Region Entity would not be sent to client. */
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getFirstEntityId() {
|
||||
return entities.stream().findFirst().orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'initAbilities'");
|
||||
}
|
||||
}
|
||||
|
||||
55
src/main/java/emu/grasscutter/game/entity/EntityScene.java
Normal file
55
src/main/java/emu/grasscutter/game/entity/EntityScene.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.AbilityData;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
|
||||
public class EntityScene extends GameEntity {
|
||||
|
||||
public EntityScene(Scene scene) {
|
||||
super(scene);
|
||||
initAbilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// Load abilities from levelElementAbilities
|
||||
for (var ability :
|
||||
GameData.getConfigGlobalCombat().getDefaultAbilities().getLevelElementAbilities()) {
|
||||
AbilityData data = GameData.getAbilityData(ability);
|
||||
if (data != null)
|
||||
getScene().getWorld().getHost().getAbilityManager().addAbilityToEntity(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityTypeId() {
|
||||
return 0x13;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
// TODO
|
||||
return new Int2FloatArrayMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
// TODO Auto-generated method stub
|
||||
return new Position(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return new Position(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.game.entity.platform.EntityPlatform;
|
||||
import emu.grasscutter.game.entity.platform.EntitySolarIsotomaElevatorPlatform;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
@@ -10,22 +9,25 @@ import lombok.Getter;
|
||||
public class EntitySolarIsotomaClientGadget extends EntityClientGadget {
|
||||
public static final int GADGET_ID = 41038001;
|
||||
public static final int ELEVATOR_GADGET_ID = 41038002;
|
||||
@Getter private EntityPlatform platformGadget;
|
||||
@Getter private EntityGadget platformGadget;
|
||||
|
||||
public EntitySolarIsotomaClientGadget(Scene scene, Player player, EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify notify) {
|
||||
public EntitySolarIsotomaClientGadget(
|
||||
Scene scene, Player player, EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify notify) {
|
||||
super(scene, player, notify);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
//Create solar isotoma elevator and send to all.
|
||||
this.platformGadget = new EntitySolarIsotomaElevatorPlatform(this, getScene(), getOwner(), ELEVATOR_GADGET_ID, getPosition(), getRotation());
|
||||
// Create solar isotoma elevator and send to all.
|
||||
this.platformGadget =
|
||||
new EntitySolarIsotomaElevatorPlatform(
|
||||
this, getScene(), ELEVATOR_GADGET_ID, getPosition(), getRotation());
|
||||
getScene().addEntity(this.platformGadget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved() {
|
||||
//Remove solar isotoma elevator entity.
|
||||
// Remove solar isotoma elevator entity.
|
||||
getScene().removeEntity(this.platformGadget);
|
||||
}
|
||||
}
|
||||
|
||||
66
src/main/java/emu/grasscutter/game/entity/EntityTeam.java
Normal file
66
src/main/java/emu/grasscutter/game/entity/EntityTeam.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.AbilityData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.World;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
|
||||
public class EntityTeam extends GameEntity {
|
||||
|
||||
private Player player;
|
||||
|
||||
public EntityTeam(Player player) {
|
||||
super(player.getScene());
|
||||
initAbilities();
|
||||
this.id = player.getWorld().getNextEntityId(EntityIdType.TEAM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// Load abilities from levelElementAbilities
|
||||
var defaultAbilities = GameData.getConfigGlobalCombat().getDefaultAbilities();
|
||||
if (defaultAbilities.getDefaultTeamAbilities() != null)
|
||||
for (var ability : defaultAbilities.getDefaultTeamAbilities()) {
|
||||
AbilityData data = GameData.getAbilityData(ability);
|
||||
if (data != null)
|
||||
player.getWorld().getHost().getAbilityManager().addAbilityToEntity(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return player.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityTypeId() {
|
||||
return EntityIdType.TEAM.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
// TODO
|
||||
return new Int2FloatArrayMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
// TODO Auto-generated method stub
|
||||
return new Position(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return new Position(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.ConfigGadget;
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityGadget;
|
||||
import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo;
|
||||
import emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair;
|
||||
@@ -21,20 +22,19 @@ import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
|
||||
import emu.grasscutter.net.proto.VehicleInfoOuterClass.VehicleInfo;
|
||||
import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
import emu.grasscutter.utils.helpers.ProtoHelper;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class EntityVehicle extends EntityBaseGadget {
|
||||
|
||||
@Getter private final Player owner;
|
||||
|
||||
@Getter(onMethod_ = @Override)
|
||||
private final Int2FloatMap fightProperties;
|
||||
|
||||
@@ -43,9 +43,10 @@ public class EntityVehicle extends EntityBaseGadget {
|
||||
|
||||
@Getter @Setter private float curStamina;
|
||||
@Getter private List<VehicleMember> vehicleMembers;
|
||||
@Nullable @Getter private ConfigGadget configGadget;
|
||||
@Nullable @Getter private ConfigEntityGadget configGadget;
|
||||
|
||||
public EntityVehicle(Scene scene, Player player, int gadgetId, int pointId, Position pos, Position rot) {
|
||||
public EntityVehicle(
|
||||
Scene scene, Player player, int gadgetId, int pointId, Position pos, Position rot) {
|
||||
super(scene, pos, rot);
|
||||
this.owner = player;
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
@@ -63,7 +64,7 @@ public class EntityVehicle extends EntityBaseGadget {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillFightProps(ConfigGadget configGadget) {
|
||||
protected void fillFightProps(ConfigEntityGadget configGadget) {
|
||||
super.fillFightProps(configGadget);
|
||||
this.addFightProperty(FightProperty.FIGHT_PROP_CUR_SPEED, 0);
|
||||
this.addFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, 0);
|
||||
@@ -72,41 +73,59 @@ public class EntityVehicle extends EntityBaseGadget {
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
|
||||
VehicleInfo vehicle = VehicleInfo.newBuilder()
|
||||
.setOwnerUid(this.owner.getUid())
|
||||
.setCurStamina(getCurStamina())
|
||||
.build();
|
||||
VehicleInfo vehicle =
|
||||
VehicleInfo.newBuilder()
|
||||
.setOwnerUid(this.owner.getUid())
|
||||
.setCurStamina(getCurStamina())
|
||||
.build();
|
||||
|
||||
EntityAuthorityInfo authority = EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(SceneEntityAiInfo.newBuilder().setIsAiOpen(true).setBornPos(getPosition().toProto()))
|
||||
.setBornPos(getPosition().toProto())
|
||||
.build();
|
||||
EntityAuthorityInfo authority =
|
||||
EntityAuthorityInfo.newBuilder()
|
||||
.setAbilityInfo(AbilitySyncStateInfo.newBuilder())
|
||||
.setRendererChangedInfo(EntityRendererChangedInfo.newBuilder())
|
||||
.setAiInfo(
|
||||
SceneEntityAiInfo.newBuilder()
|
||||
.setIsAiOpen(true)
|
||||
.setBornPos(getPosition().toProto()))
|
||||
.setBornPos(getPosition().toProto())
|
||||
.build();
|
||||
|
||||
SceneGadgetInfo.Builder gadgetInfo = SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(this.getGadgetId())
|
||||
.setAuthorityPeerId(this.getOwner().getPeerId())
|
||||
.setIsEnableInteract(true)
|
||||
.setVehicleInfo(vehicle);
|
||||
SceneGadgetInfo.Builder gadgetInfo =
|
||||
SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(this.getGadgetId())
|
||||
.setAuthorityPeerId(this.getOwner().getPeerId())
|
||||
.setIsEnableInteract(true)
|
||||
.setVehicleInfo(vehicle);
|
||||
|
||||
SceneEntityInfo.Builder entityInfo = SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setMotionInfo(MotionInfo.newBuilder().setPos(getPosition().toProto()).setRot(getRotation().toProto()).setSpeed(Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setGadget(gadgetInfo)
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
SceneEntityInfo.Builder entityInfo =
|
||||
SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setMotionInfo(
|
||||
MotionInfo.newBuilder()
|
||||
.setPos(getPosition().toProto())
|
||||
.setRot(getRotation().toProto())
|
||||
.setSpeed(Vector.newBuilder()))
|
||||
.addAnimatorParaList(AnimatorParameterValueInfoPair.newBuilder())
|
||||
.setGadget(gadgetInfo)
|
||||
.setEntityAuthorityInfo(authority)
|
||||
.setLifeState(1);
|
||||
|
||||
PropPair pair = PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 47))
|
||||
.build();
|
||||
PropPair pair =
|
||||
PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, 47))
|
||||
.build();
|
||||
|
||||
this.addAllFightPropsToEntityInfo(entityInfo);
|
||||
entityInfo.addPropList(pair);
|
||||
|
||||
return entityInfo.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'initAbilities'");
|
||||
}
|
||||
}
|
||||
|
||||
79
src/main/java/emu/grasscutter/game/entity/EntityWeapon.java
Normal file
79
src/main/java/emu/grasscutter/game/entity/EntityWeapon.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityGadget;
|
||||
import emu.grasscutter.data.binout.config.fields.ConfigAbilityData;
|
||||
import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.world.*;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import emu.grasscutter.scripts.EntityControllerScriptManager;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.*;
|
||||
|
||||
@ToString(callSuper = true)
|
||||
public class EntityWeapon extends EntityBaseGadget {
|
||||
@Getter private final GadgetData gadgetData;
|
||||
|
||||
@Getter(onMethod_ = @Override)
|
||||
@Setter
|
||||
private int gadgetId;
|
||||
|
||||
@Nullable @Getter private ConfigEntityGadget configGadget;
|
||||
|
||||
@Getter(onMethod_ = @Override, lazy = true)
|
||||
private final Int2FloatMap fightProperties = new Int2FloatOpenHashMap();
|
||||
|
||||
@Getter private final Position bornPos;
|
||||
@Getter private final Position bornRot;
|
||||
|
||||
public EntityWeapon(Scene scene, int gadgetId) {
|
||||
super(scene);
|
||||
|
||||
this.gadgetData = GameData.getGadgetDataMap().get(gadgetId);
|
||||
if (gadgetData != null && gadgetData.getJsonName() != null) {
|
||||
this.configGadget = GameData.getGadgetConfigData().get(gadgetData.getJsonName());
|
||||
}
|
||||
|
||||
this.gadgetId = gadgetId;
|
||||
this.bornPos = this.getPosition().clone();
|
||||
this.bornRot = this.getRotation().clone();
|
||||
|
||||
this.fillFightProps(configGadget);
|
||||
if (GameData.getGadgetMappingMap().containsKey(gadgetId)) {
|
||||
var controllerName = GameData.getGadgetMappingMap().get(gadgetId).getServerController();
|
||||
this.setEntityController(EntityControllerScriptManager.getGadgetController(controllerName));
|
||||
if (getEntityController() == null) {
|
||||
Grasscutter.getLogger().warn("Gadget controller {} not found.", controllerName);
|
||||
}
|
||||
}
|
||||
|
||||
this.id = scene.getWorld().getNextEntityId(EntityIdType.WEAPON);
|
||||
Grasscutter.getLogger()
|
||||
.trace("New weapon entity {} in scene {}.", this.id, this.getScene().getId());
|
||||
|
||||
this.initAbilities();
|
||||
}
|
||||
|
||||
private void addConfigAbility(ConfigAbilityData abilityData) {
|
||||
var data = GameData.getAbilityData(abilityData.getAbilityName());
|
||||
if (data != null) this.getWorld().getHost().getAbilityManager().addAbilityToEntity(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// TODO: handle pre-dynamic, static and dynamic here
|
||||
if (this.configGadget != null && this.configGadget.getAbilities() != null) {
|
||||
for (var ability : this.configGadget.getAbilities()) {
|
||||
this.addConfigAbility(ability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
66
src/main/java/emu/grasscutter/game/entity/EntityWorld.java
Normal file
66
src/main/java/emu/grasscutter/game/entity/EntityWorld.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.World;
|
||||
import emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatArrayMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import lombok.Getter;
|
||||
|
||||
public class EntityWorld extends GameEntity {
|
||||
@Getter private World world;
|
||||
|
||||
public EntityWorld(World world) {
|
||||
super(null);
|
||||
|
||||
this.world = world;
|
||||
this.id = world.getNextEntityId(EntityIdType.MPLEVEL);
|
||||
|
||||
this.initAbilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scene getScene() {
|
||||
return this.world.getHost().getScene();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initAbilities() {
|
||||
// Load abilities from levelElementAbilities
|
||||
for (var ability :
|
||||
GameData.getConfigGlobalCombat().getDefaultAbilities().getDefaultMPLevelAbilities()) {
|
||||
var data = GameData.getAbilityData(ability);
|
||||
if (data != null) world.getHost().getAbilityManager().addAbilityToEntity(this, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityTypeId() {
|
||||
return EntityIdType.TEAM.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Int2FloatMap getFightProperties() {
|
||||
// TODO
|
||||
return new Int2FloatArrayMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
// TODO Auto-generated method stub
|
||||
return new Position(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getRotation() {
|
||||
return new Position(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfo toProto() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,25 @@
|
||||
package emu.grasscutter.game.entity;
|
||||
|
||||
import emu.grasscutter.game.ability.*;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
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.game.props.*;
|
||||
import emu.grasscutter.game.world.*;
|
||||
import emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair;
|
||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
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.event.entity.EntityDamageEvent;
|
||||
import emu.grasscutter.server.event.entity.EntityDeathEvent;
|
||||
import emu.grasscutter.scripts.data.controller.EntityController;
|
||||
import emu.grasscutter.server.event.entity.*;
|
||||
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.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2FloatMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import java.util.*;
|
||||
import lombok.*;
|
||||
|
||||
public abstract class GameEntity {
|
||||
@Getter protected int id;
|
||||
@Getter private final Scene scene;
|
||||
@Getter protected int id;
|
||||
@Getter @Setter private SpawnDataEntry spawnEntry;
|
||||
|
||||
@Getter @Setter private int blockId;
|
||||
@@ -39,19 +32,31 @@ public abstract class GameEntity {
|
||||
|
||||
@Getter @Setter private boolean lockHP;
|
||||
|
||||
// Abilities
|
||||
private Object2FloatMap<String> metaOverrideMap;
|
||||
private Int2ObjectMap<String> metaModifiers;
|
||||
// Lua controller for specific actions
|
||||
@Getter @Setter private EntityController entityController;
|
||||
@Getter private ElementType lastAttackType = ElementType.None;
|
||||
|
||||
@Getter private List<Ability> instancedAbilities = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
private Int2ObjectMap<AbilityModifierController> instancedModifiers =
|
||||
new Int2ObjectOpenHashMap<>();
|
||||
|
||||
@Getter private Map<String, Float> globalAbilityValues = new HashMap<>();
|
||||
|
||||
public GameEntity(Scene scene) {
|
||||
this.scene = scene;
|
||||
this.motionState = MotionState.MOTION_STATE_NONE;
|
||||
}
|
||||
|
||||
public abstract void initAbilities();
|
||||
|
||||
public int getEntityType() {
|
||||
return this.getId() >> 24;
|
||||
}
|
||||
|
||||
public abstract int getEntityTypeId();
|
||||
|
||||
public World getWorld() {
|
||||
return this.getScene().getWorld();
|
||||
}
|
||||
@@ -64,20 +69,6 @@ public abstract class GameEntity {
|
||||
return this.isAlive() ? LifeState.LIFE_ALIVE : LifeState.LIFE_DEAD;
|
||||
}
|
||||
|
||||
public Object2FloatMap<String> getMetaOverrideMap() {
|
||||
if (this.metaOverrideMap == null) {
|
||||
this.metaOverrideMap = new Object2FloatOpenHashMap<>();
|
||||
}
|
||||
return this.metaOverrideMap;
|
||||
}
|
||||
|
||||
public Int2ObjectMap<String> getMetaModifiers() {
|
||||
if (this.metaModifiers == null) {
|
||||
this.metaModifiers = new Int2ObjectOpenHashMap<>();
|
||||
}
|
||||
return this.metaModifiers;
|
||||
}
|
||||
|
||||
public abstract Int2FloatMap getFightProperties();
|
||||
|
||||
public abstract Position getPosition();
|
||||
@@ -105,24 +96,29 @@ public abstract class GameEntity {
|
||||
}
|
||||
|
||||
public void addAllFightPropsToEntityInfo(SceneEntityInfo.Builder entityInfo) {
|
||||
this.getFightProperties().forEach((key, value) -> {
|
||||
if (key == 0) return;
|
||||
entityInfo.addFightPropList(FightPropPair.newBuilder().setPropType(key).setPropValue(value).build());
|
||||
});
|
||||
this.getFightProperties()
|
||||
.forEach(
|
||||
(key, value) -> {
|
||||
if (key == 0) return;
|
||||
entityInfo.addFightPropList(
|
||||
FightPropPair.newBuilder().setPropType(key).setPropValue(value).build());
|
||||
});
|
||||
}
|
||||
|
||||
protected MotionInfo getMotionInfo() {
|
||||
MotionInfo proto = MotionInfo.newBuilder()
|
||||
return MotionInfo.newBuilder()
|
||||
.setPos(this.getPosition().toProto())
|
||||
.setRot(this.getRotation().toProto())
|
||||
.setSpeed(Vector.newBuilder())
|
||||
.setState(this.getMotionState())
|
||||
.build();
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
public float heal(float amount) {
|
||||
return heal(amount, false);
|
||||
}
|
||||
|
||||
public float heal(float amount, boolean mute) {
|
||||
if (this.getFightProperties() == null) {
|
||||
return 0f;
|
||||
}
|
||||
@@ -137,23 +133,30 @@ public abstract class GameEntity {
|
||||
float healed = Math.min(maxHp - curHp, amount);
|
||||
this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, healed);
|
||||
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP));
|
||||
this.getScene()
|
||||
.broadcastPacket(
|
||||
new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP));
|
||||
|
||||
return healed;
|
||||
}
|
||||
|
||||
public void damage(float amount) {
|
||||
this.damage(amount, 0);
|
||||
this.damage(amount, 0, ElementType.None);
|
||||
}
|
||||
|
||||
public void damage(float amount, int killerId) {
|
||||
public void damage(float amount, ElementType attackType) {
|
||||
this.damage(amount, 0, attackType);
|
||||
}
|
||||
|
||||
public void damage(float amount, int killerId, ElementType attackType) {
|
||||
// Check if the entity has properties.
|
||||
if (this.getFightProperties() == null || !hasFightProperty(FightProperty.FIGHT_PROP_CUR_HP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Invoke entity damage event.
|
||||
EntityDamageEvent event = new EntityDamageEvent(this, amount, this.getScene().getEntityById(killerId));
|
||||
EntityDamageEvent event =
|
||||
new EntityDamageEvent(this, amount, attackType, this.getScene().getEntityById(killerId));
|
||||
event.call();
|
||||
if (event.isCanceled()) {
|
||||
return; // If the event is canceled, do not damage the entity.
|
||||
@@ -165,6 +168,8 @@ public abstract class GameEntity {
|
||||
this.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -(event.getDamage()));
|
||||
}
|
||||
|
||||
this.lastAttackType = attackType;
|
||||
|
||||
// Check if dead
|
||||
boolean isDead = false;
|
||||
if (this.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) <= 0f) {
|
||||
@@ -172,8 +177,12 @@ public abstract class GameEntity {
|
||||
isDead = true;
|
||||
}
|
||||
|
||||
this.runLuaCallbacks(event);
|
||||
|
||||
// Packets
|
||||
this.getScene().broadcastPacket(new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP));
|
||||
this.getScene()
|
||||
.broadcastPacket(
|
||||
new PacketEntityFightPropUpdateNotify(this, FightProperty.FIGHT_PROP_CUR_HP));
|
||||
|
||||
// Check if dead.
|
||||
if (isDead) {
|
||||
@@ -181,8 +190,20 @@ public abstract class GameEntity {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the Lua callbacks for {@link EntityDamageEvent}.
|
||||
*
|
||||
* @param event The damage event.
|
||||
*/
|
||||
public void runLuaCallbacks(EntityDamageEvent event) {
|
||||
if (entityController != null) {
|
||||
entityController.onBeHurt(this, event.getAttackElementType(), true); // todo is host handling
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move this entity to a new position.
|
||||
*
|
||||
* @param position The new position.
|
||||
* @param rotation The new rotation.
|
||||
*/
|
||||
@@ -194,32 +215,49 @@ public abstract class GameEntity {
|
||||
|
||||
/**
|
||||
* Called when a player interacts with this entity
|
||||
*
|
||||
* @param player Player that is interacting with this entity
|
||||
* @param interactReq Interact request protobuf data
|
||||
*/
|
||||
public void onInteract(Player player, GadgetInteractReq interactReq) {
|
||||
public void onInteract(Player player, GadgetInteractReq interactReq) {}
|
||||
|
||||
/** Called when this entity is added to the world */
|
||||
public void onCreate() {}
|
||||
|
||||
public void onRemoved() {}
|
||||
|
||||
public void onTick(int sceneTime) {
|
||||
if (entityController != null) {
|
||||
entityController.onTimer(this, sceneTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this entity is added to the world
|
||||
*/
|
||||
public void onCreate() {
|
||||
|
||||
}
|
||||
|
||||
public void onRemoved() {
|
||||
|
||||
public int onClientExecuteRequest(int param1, int param2, int param3) {
|
||||
if (entityController != null) {
|
||||
return entityController.onClientExecuteRequest(this, param1, param2, param3);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this entity dies
|
||||
*
|
||||
* @param killerId Entity id of the entity that killed this entity
|
||||
*/
|
||||
public void onDeath(int killerId) {
|
||||
// Invoke entity death event.
|
||||
EntityDeathEvent event = new EntityDeathEvent(this, killerId);
|
||||
event.call();
|
||||
|
||||
// Run Lua callbacks.
|
||||
if (entityController != null) {
|
||||
entityController.onDie(this, getLastAttackType());
|
||||
}
|
||||
}
|
||||
|
||||
/** Invoked when a global ability value is updated. */
|
||||
public void onAbilityValueUpdate() {
|
||||
// Does nothing.
|
||||
}
|
||||
|
||||
public abstract SceneEntityInfo toProto();
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package emu.grasscutter.game.entity.gadget;
|
||||
|
||||
import emu.grasscutter.game.entity.EntityBaseGadget;
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.proto.AbilityGadgetInfoOuterClass;
|
||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import lombok.val;
|
||||
|
||||
public class GadgetAbility extends GadgetContent {
|
||||
private EntityBaseGadget parent;
|
||||
|
||||
public GadgetAbility(EntityGadget gadget, EntityBaseGadget parent) {
|
||||
super(gadget);
|
||||
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public boolean onInteract(Player player, GadgetInteractReq req) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {
|
||||
if (this.parent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
val abilityGadgetInfo =
|
||||
AbilityGadgetInfoOuterClass.AbilityGadgetInfo.newBuilder()
|
||||
.setCampId(parent.getCampId())
|
||||
.setCampTargetType(parent.getCampType())
|
||||
.setTargetEntityId(parent.getId())
|
||||
.build();
|
||||
|
||||
gadgetInfo.setAbilityGadget(abilityGadgetInfo);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
package emu.grasscutter.game.entity.gadget;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.drop.DropSystem;
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.entity.gadget.chest.BossChestInteractHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.LifeState;
|
||||
import emu.grasscutter.game.props.WatcherTriggerType;
|
||||
import emu.grasscutter.net.proto.BossChestInfoOuterClass.BossChestInfo;
|
||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
import emu.grasscutter.net.proto.InterOpTypeOuterClass.InterOpType;
|
||||
@@ -13,8 +14,9 @@ import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
|
||||
import emu.grasscutter.net.proto.ResinCostTypeOuterClass;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.scripts.constants.ScriptGadgetState;
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketWorldChestOpenNotify;
|
||||
|
||||
public class GadgetChest extends GadgetContent {
|
||||
|
||||
@@ -22,23 +24,110 @@ public class GadgetChest extends GadgetContent {
|
||||
super(gadget);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether we should remove the gadget.
|
||||
*/
|
||||
public boolean onInteract(Player player, GadgetInteractReq req) {
|
||||
var chestInteractHandlerMap = getGadget().getScene().getWorld().getServer().getWorldDataSystem().getChestInteractHandlerMap();
|
||||
// If bigWorldScript enabled,use new drop system.
|
||||
if (Grasscutter.getConfig().server.game.enableScriptInBigWorld) {
|
||||
SceneGadget chest = getGadget().getMetaGadget();
|
||||
DropSystem dropSystem = player.getServer().getDropSystem();
|
||||
if (chest.boss_chest != null && chest.drop_tag != null) {
|
||||
// Boss chest drop
|
||||
// TODO:check for blossom chests
|
||||
if (req.getOpType() == InterOpType.INTER_OP_TYPE_START) {
|
||||
// Two steps
|
||||
player.sendPacket(
|
||||
new PacketGadgetInteractRsp(
|
||||
getGadget(),
|
||||
InteractType.INTERACT_TYPE_OPEN_CHEST,
|
||||
InterOpType.INTER_OP_TYPE_START));
|
||||
return false;
|
||||
}
|
||||
// TODO:check for take_num.(some boss rewards can only be claimed once a week.). Handle boss
|
||||
// respawn.
|
||||
// TODO:should return Retcode.RET_RESIN_NOT_ENOUGH ?
|
||||
if (player.getResinManager().useResin(chest.boss_chest.resin)
|
||||
&& dropSystem.handleBossChestDrop(chest.drop_tag, player)) {
|
||||
// Is it correct?
|
||||
player
|
||||
.getBattlePassManager()
|
||||
.triggerMission(
|
||||
WatcherTriggerType.TRIGGER_WORLD_BOSS_REWARD,
|
||||
chest.boss_chest.monster_config_id,
|
||||
1);
|
||||
getGadget().updateState(ScriptGadgetState.ChestOpened);
|
||||
player.sendPacket(
|
||||
new PacketGadgetInteractRsp(
|
||||
this.getGadget(),
|
||||
InteractTypeOuterClass.InteractType.INTERACT_TYPE_OPEN_CHEST,
|
||||
InterOpType.INTER_OP_TYPE_FINISH));
|
||||
return true;
|
||||
}
|
||||
// if failed,fallback to legacy drop system.
|
||||
} else {
|
||||
// Normal chest drop
|
||||
// only the owner of the world can open chests.
|
||||
if (player != player.getWorld().getHost()) return false;
|
||||
boolean status = false;
|
||||
if (chest.drop_tag != null) {
|
||||
status = dropSystem.handleChestDrop(chest.drop_tag, chest.level, getGadget());
|
||||
} else if (chest.chest_drop_id != 0) {
|
||||
status = dropSystem.handleChestDrop(chest.chest_drop_id, chest.drop_count, getGadget());
|
||||
}
|
||||
if (status) {
|
||||
getGadget().updateState(ScriptGadgetState.ChestOpened);
|
||||
player.sendPacket(
|
||||
new PacketGadgetInteractRsp(
|
||||
getGadget(),
|
||||
InteractType.INTERACT_TYPE_OPEN_CHEST,
|
||||
InterOpType.INTER_OP_TYPE_FINISH));
|
||||
player.sendPacket(
|
||||
new PacketWorldChestOpenNotify(
|
||||
getGadget().getGroupId(), player.getSceneId(), chest.config_id));
|
||||
return true;
|
||||
}
|
||||
// if failed,fallback to legacy drop system.
|
||||
}
|
||||
Grasscutter.getLogger()
|
||||
.warn(
|
||||
"Can not solve chest drop: chest_drop_id = {} , drop_tag = {}.Fallback to legacy drop system.",
|
||||
chest.chest_drop_id,
|
||||
chest.drop_tag);
|
||||
}
|
||||
|
||||
// Legacy chest drop system
|
||||
var chestInteractHandlerMap =
|
||||
getGadget()
|
||||
.getScene()
|
||||
.getWorld()
|
||||
.getServer()
|
||||
.getWorldDataSystem()
|
||||
.getChestInteractHandlerMap();
|
||||
var handler = chestInteractHandlerMap.get(getGadget().getGadgetData().getJsonName());
|
||||
if (handler == null) {
|
||||
Grasscutter.getLogger().warn("Could not found the handler of this type of Chests {}", getGadget().getGadgetData().getJsonName());
|
||||
Grasscutter.getLogger()
|
||||
.warn(
|
||||
"Could not found the handler of this type of Chests {}",
|
||||
getGadget().getGadgetData().getJsonName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (req.getOpType() == InterOpType.INTER_OP_TYPE_START && handler.isTwoStep()) {
|
||||
player.sendPacket(new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_OPEN_CHEST, InterOpType.INTER_OP_TYPE_START));
|
||||
player.sendPacket(
|
||||
new PacketGadgetInteractRsp(
|
||||
getGadget(), InteractType.INTERACT_TYPE_OPEN_CHEST, InterOpType.INTER_OP_TYPE_START));
|
||||
return false;
|
||||
}else {
|
||||
} else {
|
||||
boolean success;
|
||||
if (handler instanceof BossChestInteractHandler bossChestInteractHandler) {
|
||||
success = bossChestInteractHandler.onInteract(this, player,
|
||||
req.getResinCostType()== ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE);
|
||||
}else {
|
||||
success =
|
||||
bossChestInteractHandler.onInteract(
|
||||
this,
|
||||
player,
|
||||
req.getResinCostType()
|
||||
== ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE);
|
||||
} else {
|
||||
success = handler.onInteract(this, player);
|
||||
}
|
||||
if (!success) {
|
||||
@@ -46,7 +135,11 @@ public class GadgetChest extends GadgetContent {
|
||||
}
|
||||
|
||||
getGadget().updateState(ScriptGadgetState.ChestOpened);
|
||||
player.sendPacket(new PacketGadgetInteractRsp(this.getGadget(), InteractTypeOuterClass.InteractType.INTERACT_TYPE_OPEN_CHEST));
|
||||
player.sendPacket(
|
||||
new PacketGadgetInteractRsp(
|
||||
this.getGadget(),
|
||||
InteractTypeOuterClass.InteractType.INTERACT_TYPE_OPEN_CHEST,
|
||||
InterOpType.INTER_OP_TYPE_FINISH));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -61,13 +154,13 @@ public class GadgetChest extends GadgetContent {
|
||||
if (bossChest != null) {
|
||||
var players = getGadget().getScene().getPlayers().stream().map(Player::getUid).toList();
|
||||
|
||||
gadgetInfo.setBossChest(BossChestInfo.newBuilder()
|
||||
.setMonsterConfigId(bossChest.monster_config_id)
|
||||
.setResin(bossChest.resin)
|
||||
.addAllQualifyUidList(players)
|
||||
.addAllRemainUidList(players)
|
||||
.build());
|
||||
gadgetInfo.setBossChest(
|
||||
BossChestInfo.newBuilder()
|
||||
.setMonsterConfigId(bossChest.monster_config_id)
|
||||
.setResin(bossChest.resin)
|
||||
.addAllQualifyUidList(players)
|
||||
.addAllRemainUidList(players)
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,17 +6,17 @@ import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
|
||||
public abstract class GadgetContent {
|
||||
private final EntityGadget gadget;
|
||||
private final EntityGadget gadget;
|
||||
|
||||
public GadgetContent(EntityGadget gadget) {
|
||||
this.gadget = gadget;
|
||||
}
|
||||
public GadgetContent(EntityGadget gadget) {
|
||||
this.gadget = gadget;
|
||||
}
|
||||
|
||||
public EntityGadget getGadget() {
|
||||
return gadget;
|
||||
}
|
||||
|
||||
public abstract boolean onInteract(Player player, GadgetInteractReq req);
|
||||
|
||||
public abstract void onBuildProto(SceneGadgetInfo.Builder gadgetInfo);
|
||||
public EntityGadget getGadget() {
|
||||
return gadget;
|
||||
}
|
||||
|
||||
public abstract boolean onInteract(Player player, GadgetInteractReq req);
|
||||
|
||||
public abstract void onBuildProto(SceneGadgetInfo.Builder gadgetInfo);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package emu.grasscutter.game.entity.gadget;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.GatherData;
|
||||
import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.entity.EntityItem;
|
||||
@@ -8,22 +10,32 @@ 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.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
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.Utils;
|
||||
|
||||
public class GadgetGatherObject extends GadgetContent {
|
||||
public final class GadgetGatherObject extends GadgetContent {
|
||||
private int itemId;
|
||||
private boolean isForbidGuest;
|
||||
|
||||
public GadgetGatherObject(EntityGadget gadget) {
|
||||
super(gadget);
|
||||
|
||||
// overwrites the default spawn handling
|
||||
if (gadget.getSpawnEntry() != null) {
|
||||
this.itemId = gadget.getSpawnEntry().getGatherItemId();
|
||||
return;
|
||||
}
|
||||
|
||||
GatherData gatherData = GameData.getGatherDataMap().get(gadget.getPointType());
|
||||
if (gatherData != null) {
|
||||
this.itemId = gatherData.getItemId();
|
||||
this.isForbidGuest = gatherData.isForbidGuest();
|
||||
} else {
|
||||
Grasscutter.getLogger().trace("invalid gather object: {}", gadget.getConfigId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,32 +57,37 @@ public class GadgetGatherObject extends GadgetContent {
|
||||
GameItem item = new GameItem(itemData, 1);
|
||||
player.getInventory().addItem(item, ActionReason.Gather);
|
||||
|
||||
getGadget().getScene().broadcastPacket(new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_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();
|
||||
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);
|
||||
int times = Utils.randomRange(1, 2);
|
||||
|
||||
for (int i = 0 ; i < times ; i++) {
|
||||
EntityItem item = new EntityItem(
|
||||
scene,
|
||||
player,
|
||||
GameData.getItemDataMap().get(itemId),
|
||||
getGadget().getPosition().nearby2d(1f).addY(2f),
|
||||
1,
|
||||
true);
|
||||
for (int i = 0; i < times; i++) {
|
||||
EntityItem item =
|
||||
new EntityItem(
|
||||
scene,
|
||||
player,
|
||||
GameData.getItemDataMap().get(itemId),
|
||||
getGadget().getPosition().nearby2d(1f).addY(2f),
|
||||
1,
|
||||
true);
|
||||
|
||||
scene.addEntity(item);
|
||||
}
|
||||
|
||||
@@ -3,38 +3,45 @@ 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.GatherGadgetInfoOuterClass.GatherGadgetInfo;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
|
||||
public class GadgetGatherPoint extends GadgetContent {
|
||||
private int itemId;
|
||||
private boolean isForbidGuest;
|
||||
/** Spawner for the gather objects */
|
||||
public final class GadgetGatherPoint extends GadgetContent {
|
||||
private final GatherData gatherData;
|
||||
private final EntityGadget gatherObjectChild;
|
||||
|
||||
public GadgetGatherPoint(EntityGadget gadget) {
|
||||
super(gadget);
|
||||
|
||||
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();
|
||||
}
|
||||
this.gatherData = GameData.getGatherDataMap().get(gadget.getPointType());
|
||||
|
||||
var scene = gadget.getScene();
|
||||
gatherObjectChild = new EntityGadget(scene, gatherData.getGadgetId(), gadget.getBornPos());
|
||||
|
||||
gatherObjectChild.setBlockId(gadget.getBlockId());
|
||||
gatherObjectChild.setConfigId(gadget.getConfigId());
|
||||
gatherObjectChild.setGroupId(gadget.getGroupId());
|
||||
gatherObjectChild.getRotation().set(gadget.getRotation());
|
||||
gatherObjectChild.setState(gadget.getState());
|
||||
gatherObjectChild.setPointType(gadget.getPointType());
|
||||
gatherObjectChild.setMetaGadget(gadget.getMetaGadget());
|
||||
gatherObjectChild.buildContent();
|
||||
|
||||
gadget.getChildren().add(gatherObjectChild);
|
||||
scene.addEntity(gatherObjectChild);
|
||||
}
|
||||
|
||||
public int getItemId() {
|
||||
return this.itemId;
|
||||
return this.gatherData.getItemId();
|
||||
}
|
||||
|
||||
public boolean isForbidGuest() {
|
||||
return isForbidGuest;
|
||||
return this.gatherData.isForbidGuest();
|
||||
}
|
||||
|
||||
public boolean onInteract(Player player, GadgetInteractReq req) {
|
||||
@@ -46,34 +53,13 @@ public class GadgetGatherPoint extends GadgetContent {
|
||||
}
|
||||
|
||||
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {
|
||||
GatherGadgetInfo gatherGadgetInfo = GatherGadgetInfo.newBuilder()
|
||||
.setItemId(this.getItemId())
|
||||
.setIsForbidGuest(this.isForbidGuest())
|
||||
.build();
|
||||
// todo does official use this for the spawners?
|
||||
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),
|
||||
getGadget().getPosition().clone()
|
||||
.addY(2f)
|
||||
.addX(Utils.randomFloatRange(-1f, 1f))
|
||||
.addZ(Utils.randomFloatRange(-1f, 1f)),
|
||||
1,
|
||||
true);
|
||||
|
||||
scene.addEntity(item);
|
||||
}
|
||||
|
||||
scene.killEntity(this.getGadget(), player.getTeamManager().getCurrentAvatarEntity().getId());
|
||||
// Todo: add record
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass;
|
||||
|
||||
public class GadgetObject extends GadgetContent{
|
||||
public class GadgetObject extends GadgetContent {
|
||||
public GadgetObject(EntityGadget gadget) {
|
||||
super(gadget);
|
||||
}
|
||||
@@ -16,7 +16,5 @@ public class GadgetObject extends GadgetContent{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuildProto(SceneGadgetInfoOuterClass.SceneGadgetInfo.Builder gadgetInfo) {
|
||||
|
||||
}
|
||||
public void onBuildProto(SceneGadgetInfoOuterClass.SceneGadgetInfo.Builder gadgetInfo) {}
|
||||
}
|
||||
|
||||
@@ -5,26 +5,30 @@ import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.proto.GadgetInteractReqOuterClass.GadgetInteractReq;
|
||||
import emu.grasscutter.net.proto.InteractTypeOuterClass.InteractType;
|
||||
import emu.grasscutter.net.proto.ResinCostTypeOuterClass;
|
||||
import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetInteractRsp;
|
||||
|
||||
public class GadgetRewardStatue extends GadgetContent {
|
||||
|
||||
public GadgetRewardStatue(EntityGadget gadget) {
|
||||
super(gadget);
|
||||
}
|
||||
public final class GadgetRewardStatue extends GadgetContent {
|
||||
|
||||
public boolean onInteract(Player player, GadgetInteractReq req) {
|
||||
if (player.getScene().getChallenge() != null && player.getScene().getChallenge() instanceof DungeonChallenge dungeonChallenge) {
|
||||
dungeonChallenge.getStatueDrops(player, req);
|
||||
}
|
||||
|
||||
player.sendPacket(new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_OPEN_STATUE));
|
||||
|
||||
return false;
|
||||
}
|
||||
public GadgetRewardStatue(EntityGadget gadget) {
|
||||
super(gadget);
|
||||
}
|
||||
|
||||
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {
|
||||
|
||||
}
|
||||
public boolean onInteract(Player player, GadgetInteractReq req) {
|
||||
var dungeonManager = player.getScene().getDungeonManager();
|
||||
|
||||
if (player.getScene().getChallenge() instanceof DungeonChallenge) {
|
||||
var useCondensed =
|
||||
req.getResinCostType() == ResinCostTypeOuterClass.ResinCostType.RESIN_COST_TYPE_CONDENSE;
|
||||
dungeonManager.getStatueDrops(player, useCondensed, getGadget().getGroupId());
|
||||
}
|
||||
|
||||
player.sendPacket(
|
||||
new PacketGadgetInteractRsp(getGadget(), InteractType.INTERACT_TYPE_OPEN_STATUE));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package emu.grasscutter.game.entity.gadget;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.entity.EntityGadget;
|
||||
import emu.grasscutter.game.entity.gadget.worktop.WorktopWorktopOptionHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
@@ -10,17 +9,24 @@ import emu.grasscutter.net.proto.SceneGadgetInfoOuterClass.SceneGadgetInfo;
|
||||
import emu.grasscutter.net.proto.SelectWorktopOptionReqOuterClass.SelectWorktopOptionReq;
|
||||
import emu.grasscutter.net.proto.WorktopInfoOuterClass.WorktopInfo;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class GadgetWorktop extends GadgetContent {
|
||||
private IntSet worktopOptions;
|
||||
public final class GadgetWorktop extends GadgetContent {
|
||||
private Set<Integer> worktopOptions;
|
||||
private WorktopWorktopOptionHandler handler;
|
||||
|
||||
public GadgetWorktop(EntityGadget gadget) {
|
||||
super(gadget);
|
||||
}
|
||||
|
||||
public IntSet getWorktopOptions() {
|
||||
public Set<Integer> getWorktopOptions() {
|
||||
if (this.worktopOptions == null) {
|
||||
this.worktopOptions = new HashSet<>();
|
||||
}
|
||||
|
||||
return worktopOptions;
|
||||
}
|
||||
|
||||
@@ -43,25 +49,25 @@ public class GadgetWorktop extends GadgetContent {
|
||||
}
|
||||
|
||||
public void onBuildProto(SceneGadgetInfo.Builder gadgetInfo) {
|
||||
if (this.worktopOptions == null) {
|
||||
return;
|
||||
var options = this.getWorktopOptions();
|
||||
if (options == null) return;
|
||||
|
||||
try {
|
||||
var worktop = WorktopInfo.newBuilder().addAllOptionList(options).build();
|
||||
gadgetInfo.setWorktop(worktop);
|
||||
} catch (NullPointerException ignored) {
|
||||
// "this.wrapped" is null.
|
||||
gadgetInfo.setWorktop(
|
||||
WorktopInfo.newBuilder().addAllOptionList(Collections.emptyList()).build());
|
||||
Grasscutter.getLogger().warn("GadgetWorktop.onBuildProto: this.wrapped is null");
|
||||
}
|
||||
|
||||
WorktopInfo worktop = WorktopInfo.newBuilder()
|
||||
.addAllOptionList(this.getWorktopOptions())
|
||||
.build();
|
||||
|
||||
gadgetInfo.setWorktop(worktop);
|
||||
}
|
||||
|
||||
public void setOnSelectWorktopOptionEvent(WorktopWorktopOptionHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
public boolean onSelectWorktopOption(SelectWorktopOptionReq req) {
|
||||
if (this.handler != null) {
|
||||
this.handler.onSelectWorktopOption(this, req.getOptionId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onSelectWorktopOption(SelectWorktopOptionReq req) {
|
||||
return this.handler != null && this.handler.onSelectWorktopOption(this, req.getOptionId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,10 @@ import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BossChestInteractHandler implements ChestInteractHandler{
|
||||
public class BossChestInteractHandler implements ChestInteractHandler {
|
||||
@Override
|
||||
public boolean isTwoStep() {
|
||||
return true;
|
||||
@@ -19,23 +18,40 @@ public class BossChestInteractHandler implements ChestInteractHandler{
|
||||
|
||||
@Override
|
||||
public boolean onInteract(GadgetChest chest, Player player) {
|
||||
return this.onInteract(chest,player,false);
|
||||
return this.onInteract(chest, player, false);
|
||||
}
|
||||
|
||||
public boolean onInteract(GadgetChest chest, Player player,boolean useCondensedResin) {
|
||||
var blossomRewards = player.getScene().getBlossomManager().onReward(player,chest.getGadget(),useCondensedResin);
|
||||
if (blossomRewards!=null) {
|
||||
public boolean onInteract(GadgetChest chest, Player player, boolean useCondensedResin) {
|
||||
var blossomRewards =
|
||||
player
|
||||
.getScene()
|
||||
.getBlossomManager()
|
||||
.onReward(player, chest.getGadget(), useCondensedResin);
|
||||
if (blossomRewards != null) {
|
||||
player.getInventory().addItems(blossomRewards, ActionReason.OpenWorldBossChest);
|
||||
player.sendPacket(new PacketGadgetAutoPickDropInfoNotify(blossomRewards));
|
||||
return true;
|
||||
}
|
||||
|
||||
var worldDataManager = chest.getGadget().getScene().getWorld().getServer().getWorldDataSystem();
|
||||
var monster = chest.getGadget().getMetaGadget().group.monsters.get(chest.getGadget().getMetaGadget().boss_chest.monster_config_id);
|
||||
var monster =
|
||||
chest
|
||||
.getGadget()
|
||||
.getMetaGadget()
|
||||
.group
|
||||
.monsters
|
||||
.get(chest.getGadget().getMetaGadget().boss_chest.monster_config_id);
|
||||
var reward = worldDataManager.getRewardByBossId(monster.monster_id);
|
||||
|
||||
if (reward == null) {
|
||||
Grasscutter.getLogger().warn("Could not found the reward of boss monster {}", monster.monster_id);
|
||||
var dungeonManager = player.getScene().getDungeonManager();
|
||||
|
||||
if (dungeonManager != null) {
|
||||
return dungeonManager.getStatueDrops(
|
||||
player, useCondensedResin, chest.getGadget().getGroupId());
|
||||
}
|
||||
Grasscutter.getLogger()
|
||||
.warn("Could not found the reward of boss monster {}", monster.monster_id);
|
||||
return false;
|
||||
}
|
||||
List<GameItem> rewards = new ArrayList<>();
|
||||
|
||||
@@ -3,13 +3,13 @@ package emu.grasscutter.game.entity.gadget.chest;
|
||||
import emu.grasscutter.game.entity.gadget.GadgetChest;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.world.ChestReward;
|
||||
|
||||
import emu.grasscutter.server.event.player.PlayerOpenChestEvent;
|
||||
import java.util.Random;
|
||||
|
||||
public class NormalChestInteractHandler implements ChestInteractHandler {
|
||||
private final ChestReward chestReward;
|
||||
|
||||
public NormalChestInteractHandler(ChestReward rewardData){
|
||||
public NormalChestInteractHandler(ChestReward rewardData) {
|
||||
this.chestReward = rewardData;
|
||||
}
|
||||
|
||||
@@ -20,21 +20,35 @@ public class NormalChestInteractHandler implements ChestInteractHandler {
|
||||
|
||||
@Override
|
||||
public boolean onInteract(GadgetChest chest, Player player) {
|
||||
// Invoke open chest event.
|
||||
var event = new PlayerOpenChestEvent(player, chest, this.chestReward);
|
||||
event.call();
|
||||
if (event.isCanceled()) return true;
|
||||
|
||||
player.earnExp(chestReward.getAdvExp());
|
||||
player.getInventory().addItem(201, chestReward.getResin());
|
||||
|
||||
var mora = chestReward.getMora() * (1 + (player.getWorldLevel() - 1) * 0.5);
|
||||
player.getInventory().addItem(202, (int)mora);
|
||||
player.getInventory().addItem(202, (int) mora);
|
||||
|
||||
for(int i=0;i<chestReward.getContent().size();i++){
|
||||
chest.getGadget().getScene().addItemEntity(chestReward.getContent().get(i).getItemId(), chestReward.getContent().get(i).getCount(), chest.getGadget());
|
||||
for (int i = 0; i < chestReward.getContent().size(); i++) {
|
||||
chest
|
||||
.getGadget()
|
||||
.getScene()
|
||||
.addItemEntity(
|
||||
chestReward.getContent().get(i).getItemId(),
|
||||
chestReward.getContent().get(i).getCount(),
|
||||
chest.getGadget());
|
||||
}
|
||||
|
||||
var random = new Random(System.currentTimeMillis());
|
||||
for(int i=0;i<chestReward.getRandomCount();i++){
|
||||
for (int i = 0; i < chestReward.getRandomCount(); i++) {
|
||||
var index = random.nextInt(chestReward.getRandomContent().size());
|
||||
var item = chestReward.getRandomContent().get(index);
|
||||
chest.getGadget().getScene().addItemEntity(item.getItemId(), item.getCount(), chest.getGadget());
|
||||
chest
|
||||
.getGadget()
|
||||
.getScene()
|
||||
.addItemEntity(item.getItemId(), item.getCount(), chest.getGadget());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package emu.grasscutter.game.entity.gadget.platform;
|
||||
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.net.proto.MathQuaternionOuterClass.MathQuaternion;
|
||||
import emu.grasscutter.net.proto.MovingPlatformTypeOuterClass;
|
||||
import emu.grasscutter.net.proto.PlatformInfoOuterClass;
|
||||
|
||||
/** TODO mostly hardcoded for EntitySolarIsotomaElevatorPlatform, should be more generic */
|
||||
public class AbilityRoute extends BaseRoute {
|
||||
|
||||
private final Position basePosition;
|
||||
|
||||
public AbilityRoute(
|
||||
Position startRot, boolean startRoute, boolean isActive, Position basePosition) {
|
||||
super(startRot, startRoute, isActive);
|
||||
this.basePosition = basePosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformInfoOuterClass.PlatformInfo.Builder toProto() {
|
||||
return super.toProto()
|
||||
.setStartRot(MathQuaternion.newBuilder().setW(1.0F))
|
||||
.setPosOffset(basePosition.toProto())
|
||||
.setRotOffset(MathQuaternion.newBuilder().setW(1.0F))
|
||||
.setMovingPlatformType(
|
||||
MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_ABILITY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package emu.grasscutter.game.entity.gadget.platform;
|
||||
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.MathQuaternionOuterClass.MathQuaternion;
|
||||
import emu.grasscutter.net.proto.PlatformInfoOuterClass.PlatformInfo;
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.val;
|
||||
|
||||
public abstract class BaseRoute {
|
||||
@Getter @Setter private boolean isStarted;
|
||||
@Getter @Setter private boolean isActive;
|
||||
@Getter @Setter private Position startRot;
|
||||
@Getter @Setter private int startSceneTime;
|
||||
@Getter @Setter private int stopSceneTime;
|
||||
|
||||
BaseRoute(Position startRot, boolean isStarted, boolean isActive) {
|
||||
this.startRot = startRot;
|
||||
this.isStarted = isStarted;
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
BaseRoute(SceneGadget gadget) {
|
||||
this.startRot = gadget.rot;
|
||||
this.isStarted = gadget.start_route;
|
||||
this.isActive = gadget.start_route;
|
||||
}
|
||||
|
||||
public static BaseRoute fromSceneGadget(SceneGadget sceneGadget) {
|
||||
if (sceneGadget.route_id != 0) {
|
||||
return new ConfigRoute(sceneGadget);
|
||||
} else if (sceneGadget.is_use_point_array) {
|
||||
return new PointArrayRoute(sceneGadget);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean startRoute(Scene scene) {
|
||||
if (this.isStarted) {
|
||||
return false;
|
||||
}
|
||||
this.isStarted = true;
|
||||
this.isActive = true;
|
||||
this.startSceneTime = scene.getSceneTime() + 300;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean stopRoute(Scene scene) {
|
||||
if (!this.isStarted) {
|
||||
return false;
|
||||
}
|
||||
this.isStarted = false;
|
||||
this.isActive = false;
|
||||
this.startSceneTime = scene.getSceneTime();
|
||||
this.stopSceneTime = scene.getSceneTime();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private MathQuaternion.Builder rotAsMathQuaternion() {
|
||||
val result = MathQuaternion.newBuilder();
|
||||
if (startRot != null) {
|
||||
result.setX(startRot.getX()).setY(startRot.getY()).setZ(startRot.getZ());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public PlatformInfo.Builder toProto() {
|
||||
val result =
|
||||
PlatformInfo.newBuilder()
|
||||
.setIsStarted(isStarted)
|
||||
.setIsActive(isActive)
|
||||
.setStartRot(rotAsMathQuaternion())
|
||||
.setStartSceneTime(startSceneTime);
|
||||
if (!isStarted) {
|
||||
result.setStopSceneTime(stopSceneTime);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package emu.grasscutter.game.entity.gadget.platform;
|
||||
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.net.proto.MovingPlatformTypeOuterClass;
|
||||
import emu.grasscutter.net.proto.PlatformInfoOuterClass;
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class ConfigRoute extends BaseRoute {
|
||||
|
||||
@Getter @Setter private int routeId;
|
||||
|
||||
public ConfigRoute(SceneGadget gadget) {
|
||||
super(gadget);
|
||||
this.routeId = gadget.route_id;
|
||||
}
|
||||
|
||||
public ConfigRoute(Position startRot, boolean startRoute, boolean isActive, int routeId) {
|
||||
super(startRot, startRoute, isActive);
|
||||
this.routeId = routeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformInfoOuterClass.PlatformInfo.Builder toProto() {
|
||||
return super.toProto()
|
||||
.setRouteId(routeId)
|
||||
.setMovingPlatformType(
|
||||
MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_USE_CONFIG);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package emu.grasscutter.game.entity.gadget.platform;
|
||||
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.net.proto.MovingPlatformTypeOuterClass;
|
||||
import emu.grasscutter.net.proto.PlatformInfoOuterClass;
|
||||
import emu.grasscutter.scripts.data.SceneGadget;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/** TODO implement point array routes, read from missing resources */
|
||||
public class PointArrayRoute extends BaseRoute {
|
||||
|
||||
@Getter @Setter int currentPoint;
|
||||
@Getter @Setter int pointArrayId;
|
||||
|
||||
public PointArrayRoute(SceneGadget gadget) {
|
||||
super(gadget);
|
||||
}
|
||||
|
||||
public PointArrayRoute(
|
||||
Position startRot, boolean startRoute, boolean isActive, int pointArrayId) {
|
||||
super(startRot, startRoute, isActive);
|
||||
this.pointArrayId = pointArrayId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformInfoOuterClass.PlatformInfo.Builder toProto() {
|
||||
return super.toProto()
|
||||
.setMovingPlatformType(
|
||||
MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_ROUTE);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package emu.grasscutter.game.entity.gadget.worktop;
|
||||
|
||||
import emu.grasscutter.game.entity.gadget.GadgetWorktop;
|
||||
|
||||
public interface WorktopWorktopOptionHandler {
|
||||
boolean onSelectWorktopOption(GadgetWorktop gadgetWorktop,int option);
|
||||
boolean onSelectWorktopOption(GadgetWorktop gadgetWorktop, int option);
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
package emu.grasscutter.game.entity.platform;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.binout.ConfigGadget;
|
||||
import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.game.entity.EntityBaseGadget;
|
||||
import emu.grasscutter.game.entity.EntityClientGadget;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.*;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class EntityPlatform extends EntityBaseGadget {
|
||||
@Getter
|
||||
private final Player owner;
|
||||
@Getter(onMethod_ = @Override)
|
||||
private final int gadgetId;
|
||||
@Getter
|
||||
private final EntityClientGadget gadget;
|
||||
@Getter(onMethod_ = @Override)
|
||||
private final Int2FloatMap fightProperties;
|
||||
@Nullable
|
||||
@Getter
|
||||
private ConfigGadget configGadget;
|
||||
@Getter
|
||||
private final MovingPlatformTypeOuterClass.MovingPlatformType movingPlatformType;
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean isStarted;
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean isActive;
|
||||
|
||||
public EntityPlatform(EntityClientGadget gadget, Scene scene, Player player, int gadgetId, Position pos, Position rot, MovingPlatformTypeOuterClass.MovingPlatformType movingPlatformType) {
|
||||
super(scene, pos, rot);
|
||||
this.gadget = gadget;
|
||||
this.owner = player;
|
||||
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
|
||||
this.fightProperties = new Int2FloatOpenHashMap();
|
||||
this.movingPlatformType = movingPlatformType;
|
||||
this.gadgetId = gadgetId;
|
||||
GadgetData data = GameData.getGadgetDataMap().get(gadgetId);
|
||||
if (data != null && data.getJsonName() != null) {
|
||||
this.configGadget = GameData.getGadgetConfigData().get(data.getJsonName());
|
||||
}
|
||||
|
||||
fillFightProps(configGadget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfoOuterClass.SceneEntityInfo toProto() {
|
||||
var platform = PlatformInfoOuterClass.PlatformInfo.newBuilder()
|
||||
.setMovingPlatformType(movingPlatformType)
|
||||
.build();
|
||||
|
||||
var gadgetInfo = SceneGadgetInfoOuterClass.SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(getGadgetId())
|
||||
.setAuthorityPeerId(getOwner().getPeerId())
|
||||
.setPlatform(platform);
|
||||
|
||||
var entityInfo = SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder()
|
||||
.setEntityId(getId())
|
||||
.setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setGadget(gadgetInfo)
|
||||
.setLifeState(1);
|
||||
|
||||
this.addAllFightPropsToEntityInfo(entityInfo);
|
||||
return entityInfo.build();
|
||||
}
|
||||
|
||||
public PlatformInfoOuterClass.PlatformInfo onStartRoute() {
|
||||
return PlatformInfoOuterClass.PlatformInfo.newBuilder()
|
||||
.setStartSceneTime(getScene().getSceneTime())
|
||||
.setIsStarted(true)
|
||||
.setPosOffset(getPosition().toProto())
|
||||
.setMovingPlatformType(getMovingPlatformType())
|
||||
.setIsActive(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
public PlatformInfoOuterClass.PlatformInfo onStopRoute() {
|
||||
var sceneTime = getScene().getSceneTime();
|
||||
return PlatformInfoOuterClass.PlatformInfo.newBuilder()
|
||||
.setStartSceneTime(sceneTime)
|
||||
.setStopSceneTime(sceneTime)
|
||||
.setPosOffset(getPosition().toProto())
|
||||
.setMovingPlatformType(getMovingPlatformType())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,29 @@
|
||||
package emu.grasscutter.game.entity.platform;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.binout.ConfigGadget;
|
||||
import emu.grasscutter.game.entity.EntitySolarIsotomaClientGadget;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.data.binout.config.ConfigEntityGadget;
|
||||
import emu.grasscutter.game.entity.*;
|
||||
import emu.grasscutter.game.entity.gadget.GadgetAbility;
|
||||
import emu.grasscutter.game.entity.gadget.platform.AbilityRoute;
|
||||
import emu.grasscutter.game.world.Position;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.net.proto.*;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneTimeNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import emu.grasscutter.utils.ProtoHelper;
|
||||
|
||||
public class EntitySolarIsotomaElevatorPlatform extends EntityPlatform {
|
||||
public EntitySolarIsotomaElevatorPlatform(EntitySolarIsotomaClientGadget isotoma, Scene scene, Player player, int gadgetId, Position pos, Position rot) {
|
||||
super(isotoma, scene, player, gadgetId, pos, rot, MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_ABILITY);
|
||||
public class EntitySolarIsotomaElevatorPlatform extends EntityGadget {
|
||||
@SuppressWarnings("removal")
|
||||
public EntitySolarIsotomaElevatorPlatform(
|
||||
EntitySolarIsotomaClientGadget isotoma,
|
||||
Scene scene,
|
||||
int gadgetId,
|
||||
Position pos,
|
||||
Position rot) {
|
||||
super(scene, gadgetId, pos, rot);
|
||||
setOwner(isotoma);
|
||||
this.setRouteConfig(new AbilityRoute(rot, false, false, pos));
|
||||
this.setContent(new GadgetAbility(this, isotoma));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fillFightProps(ConfigGadget configGadget) {
|
||||
protected void fillFightProps(ConfigEntityGadget configGadget) {
|
||||
if (configGadget == null || configGadget.getCombat() == null) {
|
||||
return;
|
||||
}
|
||||
@@ -27,10 +31,10 @@ public class EntitySolarIsotomaElevatorPlatform extends EntityPlatform {
|
||||
var combatProperties = combatData.getProperty();
|
||||
|
||||
if (combatProperties.isUseCreatorProperty()) {
|
||||
//If useCreatorProperty == true, use owner's property;
|
||||
GameEntity ownerAvatar = getScene().getEntityById(getGadget().getOwnerEntityId());
|
||||
if (ownerAvatar != null) {
|
||||
getFightProperties().putAll(ownerAvatar.getFightProperties());
|
||||
// If useCreatorProperty == true, use owner's property;
|
||||
GameEntity ownerEntity = getOwner();
|
||||
if (ownerEntity != null) {
|
||||
getFightProperties().putAll(ownerEntity.getFightProperties());
|
||||
return;
|
||||
} else {
|
||||
Grasscutter.getLogger().warn("Why gadget owner is null?");
|
||||
@@ -39,98 +43,4 @@ public class EntitySolarIsotomaElevatorPlatform extends EntityPlatform {
|
||||
|
||||
super.fillFightProps(configGadget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SceneEntityInfoOuterClass.SceneEntityInfo toProto() {
|
||||
var gadget = SceneGadgetInfoOuterClass.SceneGadgetInfo.newBuilder()
|
||||
.setGadgetId(getGadgetId())
|
||||
.setOwnerEntityId(getGadget().getId())
|
||||
.setAuthorityPeerId(getOwner().getPeerId())
|
||||
.setIsEnableInteract(true)
|
||||
.setAbilityGadget(AbilityGadgetInfoOuterClass.AbilityGadgetInfo.newBuilder()
|
||||
.setCampId(getGadget().getCampId())
|
||||
.setCampTargetType(getGadget().getCampType())
|
||||
.setTargetEntityId(getGadget().getId())
|
||||
.build())
|
||||
.setPlatform(PlatformInfoOuterClass.PlatformInfo.newBuilder()
|
||||
.setStartRot(MathQuaternionOuterClass.MathQuaternion.newBuilder()
|
||||
.setW(1.0F)
|
||||
.build())
|
||||
.setPosOffset(getGadget().getPosition().toProto())
|
||||
.setRotOffset(MathQuaternionOuterClass.MathQuaternion.newBuilder()
|
||||
.setW(1.0F)
|
||||
.build())
|
||||
.setMovingPlatformType(MovingPlatformTypeOuterClass.MovingPlatformType.MOVING_PLATFORM_TYPE_ABILITY)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
var authority = EntityAuthorityInfoOuterClass.EntityAuthorityInfo.newBuilder()
|
||||
.setAiInfo(SceneEntityAiInfoOuterClass.SceneEntityAiInfo.newBuilder()
|
||||
.setIsAiOpen(true)
|
||||
.setBornPos(getGadget().getPosition().toProto()))
|
||||
.setBornPos(getGadget().getPosition().toProto())
|
||||
.build();
|
||||
|
||||
var info = SceneEntityInfoOuterClass.SceneEntityInfo.newBuilder()
|
||||
.setEntityType(ProtEntityTypeOuterClass.ProtEntityType.PROT_ENTITY_TYPE_GADGET)
|
||||
.setEntityId(getId())
|
||||
.setMotionInfo(MotionInfoOuterClass.MotionInfo.newBuilder()
|
||||
.setPos(getGadget().getPosition().toProto())
|
||||
.setRot(getGadget().getRotation().toProto())
|
||||
.build());
|
||||
|
||||
GameEntity entity = getScene().getEntityById(getGadget().getOwnerEntityId());
|
||||
if (entity instanceof EntityAvatar avatar) {
|
||||
info.addPropList(PropPairOuterClass.PropPair.newBuilder()
|
||||
.setType(PlayerProperty.PROP_LEVEL.getId())
|
||||
.setPropValue(ProtoHelper.newPropValue(PlayerProperty.PROP_LEVEL, avatar.getAvatar().getLevel()))
|
||||
.build());
|
||||
} else {
|
||||
Grasscutter.getLogger().warn("Why gadget owner doesn't exist?");
|
||||
}
|
||||
|
||||
this.addAllFightPropsToEntityInfo(info);
|
||||
|
||||
info.setLifeState(1)
|
||||
.setGadget(gadget)
|
||||
.setEntityAuthorityInfo(authority);
|
||||
|
||||
return info.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformInfoOuterClass.PlatformInfo onStartRoute() {
|
||||
setStarted(true);
|
||||
setActive(true);
|
||||
|
||||
var sceneTime = getScene().getSceneTime();
|
||||
getOwner().sendPacket(new PacketSceneTimeNotify(getOwner()));
|
||||
|
||||
return PlatformInfoOuterClass.PlatformInfo.newBuilder()
|
||||
.setStartSceneTime(sceneTime + 300)
|
||||
.setIsStarted(true)
|
||||
.setPosOffset(getPosition().toProto())
|
||||
.setRotOffset(MathQuaternionOuterClass.MathQuaternion.newBuilder()
|
||||
.setW(1.0F)
|
||||
.build())
|
||||
.setMovingPlatformType(getMovingPlatformType())
|
||||
.setIsActive(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformInfoOuterClass.PlatformInfo onStopRoute() {
|
||||
setStarted(false);
|
||||
setActive(false);
|
||||
|
||||
return PlatformInfoOuterClass.PlatformInfo.newBuilder()
|
||||
.setStartSceneTime(getScene().getSceneTime())
|
||||
.setStopSceneTime(getScene().getSceneTime())
|
||||
.setPosOffset(getPosition().toProto())
|
||||
.setRotOffset(MathQuaternionOuterClass.MathQuaternion.newBuilder()
|
||||
.setW(1.0F)
|
||||
.build())
|
||||
.setMovingPlatformType(getMovingPlatformType())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user