Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the direction of the entities #211

Merged
merged 1 commit into from
Dec 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions korangar/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ use korangar_util::texture_atlas::AtlasAllocation;
#[cfg(not(feature = "debug"))]
use ragnarok_packets::handler::NoPacketCallback;
use ragnarok_packets::{
BuyShopItemsResult, CharacterId, CharacterInformation, CharacterServerInformation, DisappearanceReason, Friend, HotbarSlot,
BuyShopItemsResult, CharacterId, CharacterInformation, CharacterServerInformation, Direction, DisappearanceReason, Friend, HotbarSlot,
SellItemsResult, SkillId, SkillType, TilePosition, UnitId, WorldPosition,
};
use renderer::InterfaceRenderer;
Expand Down Expand Up @@ -964,7 +964,7 @@ impl Client {
&mut self.path_finder,
saved_login_data.account_id,
character_information,
WorldPosition { x: 0, y: 0 },
WorldPosition::origin(),
client_tick,
);
let player = Entity::Player(player);
Expand Down Expand Up @@ -1589,6 +1589,7 @@ impl Client {
let _ = self.networking_system.player_move(WorldPosition {
x: destination.x,
y: destination.y,
direction: Direction::N,
});
}
}
Expand All @@ -1604,6 +1605,7 @@ impl Client {
WorldPosition {
x: position.x,
y: position.y,
direction: Direction::N,
}
}),
_ => Ok(()),
Expand Down
16 changes: 8 additions & 8 deletions korangar/src/world/animation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::sync::Arc;
use cgmath::{Array, Matrix4, Point3, Transform, Vector2, Vector3, Zero};
use korangar_interface::elements::PrototypeElement;
use korangar_util::container::Cacheable;
use ragnarok_packets::EntityId;
use ragnarok_packets::{Direction, EntityId};

#[cfg(feature = "debug")]
use crate::graphics::DebugRectangleInstruction;
Expand Down Expand Up @@ -82,10 +82,10 @@ impl Default for AnimationFramePart {
}

impl AnimationData {
pub fn get_frame(&self, animation_state: &AnimationState, camera: &dyn Camera, head_direction: usize) -> &AnimationFrame {
pub fn get_frame(&self, animation_state: &AnimationState, camera: &dyn Camera, direction: Direction) -> &AnimationFrame {
let camera_direction = camera.camera_direction();
let direction = (camera_direction + head_direction) % 8;
let animation_action_index = animation_state.action as usize * 8 + direction;
let direction_usize = (camera_direction + usize::from(direction)) & 7;
let animation_action_index = animation_state.action as usize * 8 + direction_usize;

let delay_index = animation_action_index % self.delays.len();
let animation_index = animation_action_index % self.animations.len();
Expand Down Expand Up @@ -143,9 +143,9 @@ impl AnimationData {
entity_id: EntityId,
entity_position: Point3<f32>,
animation_state: &AnimationState,
head_direction: usize,
direction: Direction,
) {
let frame = self.get_frame(animation_state, camera, head_direction);
let frame = self.get_frame(animation_state, camera, direction);
let world_matrix = self.calculate_world_matrix(camera, frame, entity_position);

for (index, frame_part) in frame.frame_parts.iter().enumerate() {
Expand Down Expand Up @@ -187,11 +187,11 @@ impl AnimationData {
camera: &dyn Camera,
entity_position: Point3<f32>,
animation_state: &AnimationState,
head_direction: usize,
direction: Direction,
color_external: Color,
color_internal: Color,
) {
let frame = self.get_frame(animation_state, camera, head_direction);
let frame = self.get_frame(animation_state, camera, direction);
let world_matrix = self.calculate_world_matrix(camera, frame, entity_position);
instructions.push(DebugRectangleInstruction {
world: world_matrix,
Expand Down
23 changes: 8 additions & 15 deletions korangar/src/world/entity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use korangar_networking::EntityData;
use korangar_util::pathing::{PathFinder, MAX_WALK_PATH_SIZE};
#[cfg(feature = "debug")]
use korangar_util::texture_atlas::AtlasAllocation;
use ragnarok_packets::{AccountId, CharacterInformation, ClientTick, EntityId, Sex, StatusType, WorldPosition};
use ragnarok_packets::{AccountId, CharacterInformation, ClientTick, Direction, EntityId, Sex, StatusType, WorldPosition};
#[cfg(feature = "debug")]
use wgpu::{BufferUsages, Device, Queue};

Expand Down Expand Up @@ -115,6 +115,7 @@ pub struct Common {
pub health_points: usize,
pub maximum_health_points: usize,
pub movement_speed: usize,
pub direction: Direction,
pub head_direction: usize,
pub sex: Sex,

Expand Down Expand Up @@ -345,6 +346,7 @@ impl Common {
let grid_position = Vector2::new(grid_position.x, grid_position.y);
let position = map.get_world_position(grid_position);
let head_direction = entity_data.head_direction;
let direction = entity_data.position.direction;

let movement_speed = entity_data.movement_speed as usize;
let health_points = entity_data.health_points as usize;
Expand Down Expand Up @@ -375,6 +377,7 @@ impl Common {
position,
entity_id,
job_id,
direction,
head_direction,
sex,
active_movement,
Expand Down Expand Up @@ -414,7 +417,7 @@ impl Common {
self.update_movement(map, client_tick);
self.animation_state.update(client_tick);

let frame = self.animation_data.get_frame(&self.animation_state, camera, self.head_direction);
let frame = self.animation_data.get_frame(&self.animation_state, camera, self.direction);
match frame.event {
Some(ActionEvent::Sound { key }) => {
self.sound_state.update(audio_engine, self.position, key, client_tick);
Expand Down Expand Up @@ -449,17 +452,7 @@ impl Common {

let array = last_step_position - next_step_position;
let array: &[isize; 2] = array.as_ref();
self.head_direction = match array {
[0, 1] => 0,
[1, 1] => 1,
[1, 0] => 2,
[1, -1] => 3,
[0, -1] => 4,
[-1, -1] => 5,
[-1, 0] => 6,
[-1, 1] => 7,
_ => panic!("impossible step"),
};
self.direction = (*array).into();

let last_step_position = map.get_world_position(last_step.arrival_position).to_vec();
let next_step_position = map.get_world_position(next_step.arrival_position).to_vec();
Expand Down Expand Up @@ -762,7 +755,7 @@ impl Common {
self.entity_id,
self.position,
&self.animation_state,
self.head_direction,
self.direction,
);
}

Expand All @@ -773,7 +766,7 @@ impl Common {
camera,
self.position,
&self.animation_state,
self.head_direction,
self.direction,
Color::rgb_u8(255, 0, 0),
Color::rgb_u8(0, 255, 0),
);
Expand Down
2 changes: 1 addition & 1 deletion ragnarok_packets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use ragnarok_procedural::{CharacterServer, ClientPacket, LoginServer, MapSer
#[cfg(not(feature = "derive"))]
use ragnarok_procedural::{CharacterServer, ClientPacket, LoginServer, MapServer, Packet, ServerPacket};

pub use self::position::{WorldPosition, WorldPosition2};
pub use self::position::{Direction, WorldPosition, WorldPosition2};

// To make proc macros work in korangar_interface.
extern crate self as ragnarok_packets;
Expand Down
121 changes: 101 additions & 20 deletions ragnarok_packets/src/position.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,77 @@
use ragnarok_bytes::{ByteReader, ConversionResult, FromBytes, ToBytes};
use ragnarok_bytes::{ByteConvertable, ByteReader, ConversionResult, FromBytes, ToBytes};

#[derive(Debug, Copy, Clone, ByteConvertable)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
pub enum Direction {
N = 0,
NE = 1,
E = 2,
SE = 3,
S = 4,
SW = 5,
W = 6,
NW = 7,
}

impl From<Direction> for usize {
fn from(value: Direction) -> Self {
value as usize
}
}

impl From<usize> for Direction {
fn from(value: usize) -> Self {
let value = value & 7;

match value {
0 => Direction::N,
1 => Direction::NE,
2 => Direction::E,
3 => Direction::SE,
4 => Direction::S,
5 => Direction::SW,
6 => Direction::W,
7 => Direction::NW,
_ => unreachable!(),
}
}
}

impl From<[isize; 2]> for Direction {
fn from(value: [isize; 2]) -> Self {
match value {
[0, 1] => Direction::N,
[1, 1] => Direction::NE,
[1, 0] => Direction::E,
[1, -1] => Direction::SE,
[0, -1] => Direction::S,
[-1, -1] => Direction::SW,
[-1, 0] => Direction::W,
[-1, 1] => Direction::NW,
_ => panic!("impossible direction"),
}
}
}

#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "interface", derive(korangar_interface::elements::PrototypeElement))]
pub struct WorldPosition {
pub x: usize,
pub y: usize,
pub direction: Direction,
}

impl WorldPosition {
pub fn new(x: usize, y: usize) -> Self {
Self { x, y }
pub fn new(x: usize, y: usize, direction: Direction) -> Self {
Self { x, y, direction }
}

pub fn origin() -> Self {
Self {
x: 0,
y: 0,
direction: Direction::N,
}
}
}

Expand All @@ -19,19 +81,25 @@ impl FromBytes for WorldPosition {

let x = (coordinates[1] >> 6) | (coordinates[0] << 2);
let y = (coordinates[2] >> 4) | ((coordinates[1] & 0b111111) << 4);
//let direction = ...
let mut direction = coordinates[2] & 0b1111;
direction = (8 - direction + 4) & 7;

Ok(Self { x, y })
Ok(Self {
x,
y,
direction: direction.into(),
})
}
}

impl ToBytes for WorldPosition {
fn to_bytes(&self) -> ConversionResult<Vec<u8>> {
let mut coordinates = vec![0, 0, 0];
let direction = (8 - usize::from(self.direction) + 4) & 7;

coordinates[0] = (self.x >> 2) as u8;
coordinates[1] = ((self.x << 6) as u8) | (((self.y >> 4) & 0x3F) as u8);
coordinates[2] = (self.y << 4) as u8;
coordinates[2] = (self.y << 4) as u8 | (direction & 0xF) as u8;

Ok(coordinates)
}
Expand All @@ -44,18 +112,33 @@ pub struct WorldPosition2 {
pub y1: usize,
pub x2: usize,
pub y2: usize,
pub unknown: usize,
}

impl WorldPosition2 {
pub fn new(x1: usize, y1: usize, x2: usize, y2: usize) -> Self {
Self { x1, y1, x2, y2 }
Self {
x1,
y1,
x2,
y2,
unknown: 0,
}
}

pub fn to_origin_destination(self) -> (WorldPosition, WorldPosition) {
(WorldPosition { x: self.x1, y: self.y1 }, WorldPosition {
x: self.x2,
y: self.y2,
})
(
WorldPosition {
x: self.x1,
y: self.y1,
direction: Direction::N,
},
WorldPosition {
x: self.x2,
y: self.y2,
direction: Direction::N,
},
)
}
}

Expand All @@ -67,9 +150,9 @@ impl FromBytes for WorldPosition2 {
let y1 = (coordinates[2] >> 4) | ((coordinates[1] & 0b111111) << 4);
let x2 = (coordinates[3] >> 2) | ((coordinates[2] & 0b1111) << 6);
let y2 = coordinates[4] | ((coordinates[3] & 0b11) << 8);
//let direction = ...
let unknown = coordinates[5];

Ok(Self { x1, y1, x2, y2 })
Ok(Self { x1, y1, x2, y2, unknown })
}
}

Expand All @@ -82,6 +165,7 @@ impl ToBytes for WorldPosition2 {
bytes[2] = ((self.y1 << 4) as u8) | ((self.x2 >> 6) as u8);
bytes[3] = ((self.x2 << 2) as u8) | ((self.y2 >> 8) as u8);
bytes[4] = self.y2 as u8;
bytes[5] = self.unknown as u8;

Ok(bytes)
}
Expand All @@ -95,10 +179,9 @@ mod conversion {

#[test]
fn world_position() {
// Since we don't save the orientation when deserializing, this is a lossy
// operation. So we construct some test cases that igonore the bits in
// question.
let cases = [[255, 0, 0], [0, 255, 0], [0, 0, 240]];
// The direction must be between 0 and 7 inclusive.
let direction = [0, 3, 7];
let cases = [[255, 0, 0 + direction[0]], [0, 255, 0 + direction[1]], [0, 0, 240 + direction[2]]];

for case in cases {
let mut byte_reader = ragnarok_bytes::ByteReader::without_metadata(&case);
Expand All @@ -112,15 +195,13 @@ mod conversion {

#[test]
fn world_position_2() {
// Since we don't save the orientation when deserializing, this is a lossy
// operation. So we construct some test cases that igonore the bits in
// question.
let cases = [
[255, 0, 0, 0, 0, 0],
[0, 255, 0, 0, 0, 0],
[0, 0, 255, 0, 0, 0],
[0, 0, 0, 255, 0, 0],
[0, 0, 0, 0, 255, 0],
[0, 0, 0, 0, 0, 255],
];

for case in cases {
Expand Down
Loading