Added allow_players flag to Transform character state

This commit is contained in:
crabman 2024-02-28 15:56:12 +00:00
parent a14c2f054c
commit c50f1047f7
No known key found for this signature in database
6 changed files with 46 additions and 9 deletions

View File

@ -3,4 +3,5 @@ Transform(
recover_duration: 0.5, recover_duration: 0.5,
target: "common.entity.wild.peaceful.crab", target: "common.entity.wild.peaceful.crab",
specifier: Some(Evolve), specifier: Some(Evolve),
allow_players: true,
) )

View File

@ -1004,6 +1004,10 @@ pub enum CharacterAbility {
target: String, target: String,
#[serde(default)] #[serde(default)]
specifier: Option<transform::FrontendSpecifier>, specifier: Option<transform::FrontendSpecifier>,
/// Only set to `true` for admin only abilities since this disables
/// persistence and is not intended to be used by regular players
#[serde(default)]
allow_players: bool,
#[serde(default)] #[serde(default)]
meta: AbilityMeta, meta: AbilityMeta,
}, },
@ -1678,6 +1682,7 @@ impl CharacterAbility {
ref mut recover_duration, ref mut recover_duration,
target: _, target: _,
specifier: _, specifier: _,
allow_players: _,
meta: _, meta: _,
} => { } => {
*buildup_duration /= stats.speed; *buildup_duration /= stats.speed;
@ -2964,12 +2969,14 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
recover_duration, recover_duration,
target, target,
specifier, specifier,
allow_players,
meta: _, meta: _,
} => CharacterState::Transform(transform::Data { } => CharacterState::Transform(transform::Data {
static_data: transform::StaticData { static_data: transform::StaticData {
buildup_duration: Duration::from_secs_f32(*buildup_duration), buildup_duration: Duration::from_secs_f32(*buildup_duration),
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
specifier: *specifier, specifier: *specifier,
allow_players: *allow_players,
target: target.to_owned(), target: target.to_owned(),
ability_info, ability_info,
}, },

View File

@ -261,7 +261,13 @@ pub struct SetPetStayEvent(pub EcsEntity, pub EcsEntity, pub bool);
pub struct PossessEvent(pub Uid, pub Uid); pub struct PossessEvent(pub Uid, pub Uid);
pub struct TransformEvent(pub Uid, pub EntityInfo); pub struct TransformEvent {
pub target_entity: Uid,
pub entity_info: EntityInfo,
/// If set to false, players wont be transformed unless with a Possessor
/// presence kind
pub allow_players: bool,
}
pub struct InitializeCharacterEvent { pub struct InitializeCharacterEvent {
pub entity: EcsEntity, pub entity: EcsEntity,

View File

@ -32,6 +32,8 @@ pub struct StaticData {
/// The entity configuration you will be transformed into /// The entity configuration you will be transformed into
pub target: String, pub target: String,
pub ability_info: AbilityInfo, pub ability_info: AbilityInfo,
/// Whether players are allowed to transform
pub allow_players: bool,
/// Used to specify the transformation to the frontend /// Used to specify the transformation to the frontend
pub specifier: Option<FrontendSpecifier>, pub specifier: Option<FrontendSpecifier>,
} }
@ -95,7 +97,11 @@ impl CharacterBehavior for Data {
} }
} }
output_events.emit_server(TransformEvent(*data.uid, entity_info)); output_events.emit_server(TransformEvent {
target_entity: *data.uid,
entity_info,
allow_players: self.static_data.allow_players,
});
update.character = CharacterState::Transform(Data { update.character = CharacterState::Transform(Data {
static_data: self.static_data.clone(), static_data: self.static_data.clone(),
timer: Duration::default(), timer: Duration::default(),

View File

@ -662,7 +662,7 @@ fn handle_into_npc(
None, None,
); );
transform_entity(server, target, entity_info).map_err(|error| match error { transform_entity(server, target, entity_info, true).map_err(|error| match error {
TransformEntityError::EntityDead => { TransformEntityError::EntityDead => {
Content::localized_with_args("command-entity-dead", [("entity", "target")]) Content::localized_with_args("command-entity-dead", [("entity", "target")])
}, },
@ -675,6 +675,11 @@ fn handle_into_npc(
TransformEntityError::LoadingCharacter => { TransformEntityError::LoadingCharacter => {
Content::localized("command-transform-invalid-presence") Content::localized("command-transform-invalid-presence")
}, },
TransformEntityError::EntityIsPlayer => {
unreachable!(
"Transforming players must be valid as we explicitly allowed player transformation"
);
},
}) })
} }

View File

@ -2101,13 +2101,20 @@ impl ServerEvent for StartTeleportingEvent {
} }
} }
pub fn handle_transform(server: &mut Server, TransformEvent(uid, info): TransformEvent) { pub fn handle_transform(
let Some(entity) = server.state().ecs().entity_from_uid(uid) else { server: &mut Server,
TransformEvent {
target_entity,
entity_info,
allow_players,
}: TransformEvent,
) {
let Some(entity) = server.state().ecs().entity_from_uid(target_entity) else {
return; return;
}; };
if let Err(error) = transform_entity(server, entity, info) { if let Err(error) = transform_entity(server, entity, entity_info, allow_players) {
error!(?error, ?uid, "Failed transform entity"); error!(?error, ?target_entity, "Failed transform entity");
} }
} }
@ -2117,19 +2124,21 @@ pub enum TransformEntityError {
UnexpectedNpcWaypoint, UnexpectedNpcWaypoint,
UnexpectedNpcTeleporter, UnexpectedNpcTeleporter,
LoadingCharacter, LoadingCharacter,
EntityIsPlayer,
} }
pub fn transform_entity( pub fn transform_entity(
server: &mut Server, server: &mut Server,
entity: Entity, entity: Entity,
info: EntityInfo, entity_info: EntityInfo,
allow_players: bool,
) -> Result<(), TransformEntityError> { ) -> Result<(), TransformEntityError> {
let is_player = server let is_player = server
.state() .state()
.read_storage::<comp::Player>() .read_storage::<comp::Player>()
.contains(entity); .contains(entity);
match NpcData::from_entity_info(info) { match NpcData::from_entity_info(entity_info) {
NpcData::Data { NpcData::Data {
inventory, inventory,
stats, stats,
@ -2174,6 +2183,9 @@ pub fn transform_entity(
Some(PresenceKind::Spectator | PresenceKind::LoadingCharacter(_)) => { Some(PresenceKind::Spectator | PresenceKind::LoadingCharacter(_)) => {
return Err(TransformEntityError::LoadingCharacter); return Err(TransformEntityError::LoadingCharacter);
}, },
Some(PresenceKind::Character(_)) if !allow_players => {
return Err(TransformEntityError::EntityIsPlayer);
},
Some(PresenceKind::Possessor | PresenceKind::Character(_)) => {}, Some(PresenceKind::Possessor | PresenceKind::Character(_)) => {},
None => break 'persist, None => break 'persist,
} }