M client/src/gateway.ts => client/src/gateway.ts +5 -0
@@ 16,6 16,8 @@ import {
MessageS2CHello_packetInfo,
MessageS2CModuleAdd,
MessageS2CModuleAdd_packetInfo,
+ MessageS2CModuleRemove,
+ MessageS2CModuleRemove_packetInfo,
MessageS2CModulesUpdate,
MessageS2CModulesUpdate_packetInfo,
MessageS2CModuleTreeUpdate,
@@ 194,6 196,9 @@ export async function gateway_connect(gateway_url: string, username: string): Pr
children: pkt.module!.children,
};
global.tree.set(pkt.module!.id, module);
+ } else if (pkt_id == MessageS2CModuleRemove_packetInfo.type) {
+ let pkt = MessageS2CModuleRemove.decode(pkt_data);
+ global.clicked = pkt.module!.id;
} else if (pkt_id == MessageS2CModuleTreeUpdate_packetInfo.type) {
let pkt = MessageS2CModuleTreeUpdate.decode(pkt_data);
let modules: Map<number, AttachedModule> = new Map<number, AttachedModule>();
M client/src/index.ts => client/src/index.ts +17 -3
@@ 7,7 7,7 @@ import {
MessageC2SAuthenticateAndBeamOut,
MessageC2SAuthenticateAndBeamOut_packetInfo,
MessageC2SInput,
- MessageC2SInput_packetInfo, MessageC2SModuleGrabBegin, MessageC2SModuleGrabBegin_packetInfo, MessageC2SModuleGrabEnd, MessageC2SModuleGrabEnd_packetInfo, MessageC2SMouseInput, MessageC2SMouseInput_packetInfo
+ MessageC2SInput_packetInfo, MessageC2SModuleDetach, MessageC2SModuleDetach_packetInfo, MessageC2SModuleGrabBegin, MessageC2SModuleGrabBegin_packetInfo, MessageC2SModuleGrabEnd, MessageC2SModuleGrabEnd_packetInfo, MessageC2SMouseInput, MessageC2SMouseInput_packetInfo
} from "./protocol/message_c2s";
import {encode} from "./serde";
import {InputType} from "./protocol/input";
@@ 156,10 156,25 @@ async function client_main(server: string, username: string, texture_quality: st
worldposY: worldY,
}).finish();
global.clicked = global.modules[i].id;
- global.client?.socket.send(encode(MessageC2SModuleGrabBegin_packetInfo.type, msg))
+ global.client?.socket.send(encode(MessageC2SModuleGrabBegin_packetInfo.type, msg));
}
}
}
+ global.tree.forEach((value: AttachedModule, key: number) => {
+ let relativeX = value.x - worldX;
+ let relativeY = value.y - worldY;
+ let rot = -value.rotation;
+ relativeX = relativeX*Math.cos(rot) - relativeY*Math.sin(rot);
+ relativeY = relativeX*Math.sin(rot) + relativeY*Math.cos(rot);
+ if (-25 < relativeX && relativeX < 25) {
+ if (-25 < relativeY && relativeY < 25) {
+ let msg = MessageC2SModuleDetach.encode({
+ moduleId: key,
+ }).finish();
+ global.client?.socket.send(encode(MessageC2SModuleDetach_packetInfo.type, msg));
+ }
+ }
+ });
let msg = MessageC2SMouseInput.encode({
worldposX: worldX,
@@ 379,7 394,6 @@ async function client_main(server: string, username: string, texture_quality: st
global.tree.forEach((value: AttachedModule, _key: number) => {
if (global.me !== null) {
- console.log(value.x + ", " + value.y);
// @ts-ignore
let tex = global.spritesheet!["frames"][module_type_to_tex_id(value.module_type, true)];
M client/src/protocol/message_c2s.ts => client/src/protocol/message_c2s.ts +95 -2
@@ 333,7 333,7 @@ export interface MessageC2SModuleGrabEnd {
export enum MessageC2SModuleGrabEnd_packetInfo {
unknown = 0,
- type = 16,
+ type = 15,
UNRECOGNIZED = -1,
}
@@ 342,7 342,7 @@ export function messageC2SModuleGrabEnd_packetInfoFromJSON(object: any): Message
case 0:
case "unknown":
return MessageC2SModuleGrabEnd_packetInfo.unknown;
- case 16:
+ case 15:
case "type":
return MessageC2SModuleGrabEnd_packetInfo.type;
case -1:
@@ 364,6 364,43 @@ export function messageC2SModuleGrabEnd_packetInfoToJSON(object: MessageC2SModul
}
}
+export interface MessageC2SModuleDetach {
+ moduleId: number;
+}
+
+export enum MessageC2SModuleDetach_packetInfo {
+ unknown = 0,
+ type = 16,
+ UNRECOGNIZED = -1,
+}
+
+export function messageC2SModuleDetach_packetInfoFromJSON(object: any): MessageC2SModuleDetach_packetInfo {
+ switch (object) {
+ case 0:
+ case "unknown":
+ return MessageC2SModuleDetach_packetInfo.unknown;
+ case 16:
+ case "type":
+ return MessageC2SModuleDetach_packetInfo.type;
+ case -1:
+ case "UNRECOGNIZED":
+ default:
+ return MessageC2SModuleDetach_packetInfo.UNRECOGNIZED;
+ }
+}
+
+export function messageC2SModuleDetach_packetInfoToJSON(object: MessageC2SModuleDetach_packetInfo): string {
+ switch (object) {
+ case MessageC2SModuleDetach_packetInfo.unknown:
+ return "unknown";
+ case MessageC2SModuleDetach_packetInfo.type:
+ return "type";
+ case MessageC2SModuleDetach_packetInfo.UNRECOGNIZED:
+ default:
+ return "UNRECOGNIZED";
+ }
+}
+
function createBaseMessageC2SHello(): MessageC2SHello {
return { version: 0, requestedUsername: "", nextState: 0, token: "", user: "" };
}
@@ 1067,6 1104,62 @@ export const MessageC2SModuleGrabEnd = {
},
};
+function createBaseMessageC2SModuleDetach(): MessageC2SModuleDetach {
+ return { moduleId: 0 };
+}
+
+export const MessageC2SModuleDetach = {
+ encode(message: MessageC2SModuleDetach, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+ if (message.moduleId !== 0) {
+ writer.uint32(8).uint32(message.moduleId);
+ }
+ return writer;
+ },
+
+ decode(input: _m0.Reader | Uint8Array, length?: number): MessageC2SModuleDetach {
+ const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
+ let end = length === undefined ? reader.len : reader.pos + length;
+ const message = createBaseMessageC2SModuleDetach();
+ while (reader.pos < end) {
+ const tag = reader.uint32();
+ switch (tag >>> 3) {
+ case 1:
+ if (tag != 8) {
+ break;
+ }
+
+ message.moduleId = reader.uint32();
+ continue;
+ }
+ if ((tag & 7) == 4 || tag == 0) {
+ break;
+ }
+ reader.skipType(tag & 7);
+ }
+ return message;
+ },
+
+ fromJSON(object: any): MessageC2SModuleDetach {
+ return { moduleId: isSet(object.moduleId) ? Number(object.moduleId) : 0 };
+ },
+
+ toJSON(message: MessageC2SModuleDetach): unknown {
+ const obj: any = {};
+ message.moduleId !== undefined && (obj.moduleId = Math.round(message.moduleId));
+ return obj;
+ },
+
+ create<I extends Exact<DeepPartial<MessageC2SModuleDetach>, I>>(base?: I): MessageC2SModuleDetach {
+ return MessageC2SModuleDetach.fromPartial(base ?? {});
+ },
+
+ fromPartial<I extends Exact<DeepPartial<MessageC2SModuleDetach>, I>>(object: I): MessageC2SModuleDetach {
+ const message = createBaseMessageC2SModuleDetach();
+ message.moduleId = object.moduleId ?? 0;
+ return message;
+ },
+};
+
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
export type DeepPartial<T> = T extends Builtin ? T
M client/src/protocol/message_s2c.ts => client/src/protocol/message_s2c.ts +6 -6
@@ 352,7 352,7 @@ export function messageS2CModuleAdd_packetInfoToJSON(object: MessageS2CModuleAdd
}
export interface MessageS2CModuleRemove {
- module: AttachedModule | undefined;
+ module: Module | undefined;
}
export enum MessageS2CModuleRemove_packetInfo {
@@ 948,7 948,7 @@ function createBaseMessageS2CModuleRemove(): MessageS2CModuleRemove {
export const MessageS2CModuleRemove = {
encode(message: MessageS2CModuleRemove, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
if (message.module !== undefined) {
- AttachedModule.encode(message.module, writer.uint32(10).fork()).ldelim();
+ Module.encode(message.module, writer.uint32(10).fork()).ldelim();
}
return writer;
},
@@ 965,7 965,7 @@ export const MessageS2CModuleRemove = {
break;
}
- message.module = AttachedModule.decode(reader, reader.uint32());
+ message.module = Module.decode(reader, reader.uint32());
continue;
}
if ((tag & 7) == 4 || tag == 0) {
@@ 977,12 977,12 @@ export const MessageS2CModuleRemove = {
},
fromJSON(object: any): MessageS2CModuleRemove {
- return { module: isSet(object.module) ? AttachedModule.fromJSON(object.module) : undefined };
+ return { module: isSet(object.module) ? Module.fromJSON(object.module) : undefined };
},
toJSON(message: MessageS2CModuleRemove): unknown {
const obj: any = {};
- message.module !== undefined && (obj.module = message.module ? AttachedModule.toJSON(message.module) : undefined);
+ message.module !== undefined && (obj.module = message.module ? Module.toJSON(message.module) : undefined);
return obj;
},
@@ 993,7 993,7 @@ export const MessageS2CModuleRemove = {
fromPartial<I extends Exact<DeepPartial<MessageS2CModuleRemove>, I>>(object: I): MessageS2CModuleRemove {
const message = createBaseMessageS2CModuleRemove();
message.module = (object.module !== undefined && object.module !== null)
- ? AttachedModule.fromPartial(object.module)
+ ? Module.fromPartial(object.module)
: undefined;
return message;
},
M protocol/src/lib.rs => protocol/src/lib.rs +12 -1
@@ 1,6 1,7 @@
use crate::message_c2s::{
MessageC2SAuthenticateAndBeamOut, MessageC2SChat, MessageC2SGoodbye, MessageC2SHello,
- MessageC2SInput, MessageC2SModuleGrabBegin, MessageC2SModuleGrabEnd, MessageC2SMouseInput, MessageC2SPing,
+ MessageC2SInput, MessageC2SModuleDetach, MessageC2SModuleGrabBegin, MessageC2SModuleGrabEnd,
+ MessageC2SMouseInput, MessageC2SPing
};
use crate::message_s2c::{
MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CModulesUpdate,
@@ 28,6 29,7 @@ pub enum MessageC2S {
MouseInput(MessageC2SMouseInput),
ModuleGrabBegin(MessageC2SModuleGrabBegin),
ModuleGrabEnd(MessageC2SModuleGrabEnd),
+ ModuleDetach(MessageC2SModuleDetach),
}
#[derive(Debug)]
@@ 89,6 91,11 @@ impl TryFrom<&[u8]> for MessageC2S {
{
MessageC2S::ModuleGrabEnd(MessageC2SModuleGrabEnd::parse_from_bytes(&pkt.packet_data)?)
}
+ _id if _id
+ == message_c2s::message_c2smodule_detach::Packet_info::type_.value() as i64 =>
+ {
+ MessageC2S::ModuleDetach(MessageC2SModuleDetach::parse_from_bytes(&pkt.packet_data)?)
+ }
_id => {
return Err(format!("Unrecognized C2S packet {}", _id).into());
}
@@ 139,6 146,10 @@ impl TryInto<Vec<u8>> for MessageC2S {
message_c2s::message_c2smodule_grab_end::Packet_info::type_.value(),
p.write_to_bytes()?,
),
+ MessageC2S::ModuleDetach(p) => (
+ message_c2s::message_c2smodule_detach::Packet_info::type_.value(),
+ p.write_to_bytes()?,
+ ),
};
let pkt = PacketWrapper {
M protocol/src/pbuf/message_c2s.proto => protocol/src/pbuf/message_c2s.proto +7 -1
@@ 68,9 68,15 @@ message MessageC2SModuleGrabBegin {
}
message MessageC2SModuleGrabEnd {
- enum packet_info { unknown = 0; type = 0x10; }
+ enum packet_info { unknown = 0; type = 0x0f; }
uint32 module_id = 1;
double worldpos_x = 2;
double worldpos_y = 3;
}
+
+message MessageC2SModuleDetach {
+ enum packet_info { unknown = 0; type = 0x10; }
+
+ uint32 module_id = 1;
+}
M protocol/src/pbuf/message_s2c.proto => protocol/src/pbuf/message_s2c.proto +1 -1
@@ 65,5 65,5 @@ message MessageS2CModuleAdd {
message MessageS2CModuleRemove {
enum packet_info { unknown = 0; type = 0x0e; }
- protocol.module.AttachedModule module = 1;
+ protocol.module.Module module = 1;
}
M server/src/entity.rs => server/src/entity.rs +1 -1
@@ 185,7 185,7 @@ impl EntityHandler {
}
}
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub enum Entity {
Player(Player),
Planet(Planet),
M server/src/handler.rs => server/src/handler.rs +33 -2
@@ 10,7 10,7 @@ use async_std::{channel::Receiver, sync::RwLock};
use async_tungstenite::WebSocketStream;
use futures::stream::{SplitSink, SplitStream};
use futures::{FutureExt, SinkExt, StreamExt};
-use log::{debug, error, info, warn};
+use log::{debug, error, info, warn, trace};
use nalgebra::{point, vector, Matrix, Vector2};
use rand::Rng;
use rapier2d_f64::prelude::{
@@ 19,7 19,7 @@ use rapier2d_f64::prelude::{
use starkingdoms_protocol::goodbye_reason::GoodbyeReason;
use starkingdoms_protocol::message_s2c::{
MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CModulesUpdate,
- MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong, MessageS2CModuleAdd, MessageS2CModuleTreeUpdate,
+ MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong, MessageS2CModuleAdd, MessageS2CModuleTreeUpdate, MessageS2CModuleRemove,
};
use starkingdoms_protocol::module::ModuleType;
use starkingdoms_protocol::state::State;
@@ 444,6 444,37 @@ pub async fn handle_client(
MessageC2S::MouseInput(p) => {
//debug!("[{}] player input: {:?}", remote_addr, p);
}
+ MessageC2S::ModuleDetach(p) => {
+ let mut entities = entities.write().await;
+ let mut data_handle = data.write().await;
+ let mut module: Option<AttachedModule> = None;
+ debug!("[{}] detach: {:?}", remote_addr, p);
+ debug!("[{}] {:?}", remote_addr, entities.entities);
+ if let Entity::AttachedModule(p_module) = entities.entities.get_mut(&p.module_id).unwrap() {
+ module = Some(p_module.clone());
+ }
+ let player_id = entities.get_player_id(remote_addr).unwrap();
+ let module_id = AttachedModule::detach(&mut data_handle, &mut entities,
+ player_id,
+ module.unwrap());
+ let module = entities.get_module_from_id(module_id).unwrap();
+ let body = data_handle.rigid_body_set.get(module.handle).unwrap();
+ let prot_module = starkingdoms_protocol::module::Module {
+ module_type: module.module_type.into(),
+ rotation: body.rotation().angle(),
+ x: body.translation().x * SCALE,
+ y: body.translation().y * SCALE,
+ id: module_id,
+ flags: module.flags,
+ special_fields: Default::default(),
+ };
+ let msg = MessageS2C::ModuleRemove(MessageS2CModuleRemove {
+ module: Some(prot_module).into(),
+ special_fields: Default::default(),
+ })
+ .try_into()?;
+ send!(client_tx, msg).await?;
+ }
MessageC2S::ModuleGrabBegin(p) => {
if let Entity::Module(module) = entities.write().await.entities.get_mut(&p.module_id).unwrap() {
//debug!("[{}] grab begin: {:?}, flags: {}", remote_addr, p, module.flags);
M server/src/manager.rs => server/src/manager.rs +22 -2
@@ 26,7 26,7 @@ pub struct ClientManager {
pub usernames: Arc<RwLock<HashMap<SocketAddr, String>>>,
}
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct Player {
pub handle: RigidBodyHandle,
pub input: PlayerInput,
@@ 53,9 53,29 @@ impl Player {
}
modules
}
+ pub fn find_parent(&self, module: AttachedModule, entities: &EntityHandler) -> Option<(u8, EntityId)> {
+ for (slot, attachment) in self.children.iter().enumerate() {
+ if let Some(attachment) = attachment {
+ if let Entity::AttachedModule(child_module) =
+ entities.entities.get(&attachment.child).unwrap()
+ {
+ debug!("player child: {:?}", *child_module);
+ debug!("player target: {:?}", module);
+ if *child_module == module {
+ return Some((slot as u8, entities.get_player_id(self.addr).unwrap()));
+ }
+ let parent = child_module.find_parent(module.clone(), entities);
+ if let Some(_) = parent {
+ return parent;
+ }
+ }
+ }
+ }
+ None
+ }
}
-#[derive(Default, Clone)]
+#[derive(Default, Clone, Debug)]
pub struct PlayerInput {
pub up: bool,
pub left: bool,
M server/src/module.rs => server/src/module.rs +88 -2
@@ 22,7 22,7 @@ pub struct ModuleTemplate {
pub module_type: ModuleType,
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
pub struct AttachedModule {
pub handle: RigidBodyHandle,
pub module_type: ModuleType,
@@ 151,6 151,71 @@ impl AttachedModule {
entities.entities = entity_map;
Ok(attached_id)
}
+ pub fn detach(
+ data: &mut PhysicsData,
+ entities: &mut EntityHandler,
+ player_id: EntityId,
+ module: AttachedModule,
+ ) -> EntityId {
+ let mut entity_map = entities.entities.clone();
+
+ // player not in parent search
+ // also no parents included in parent search
+ let player = entities.get_player_from_id(player_id).unwrap();
+ let (slot, parent_id) = player.find_parent(module.clone(), entities).unwrap();
+ let parent_entity = entity_map
+ .get_mut(&parent_id)
+ .expect("parent id does not exist");
+
+ match parent_entity {
+ Entity::Player(ref mut player) => {
+ if let Some(child) = player.children[slot as usize].clone() {
+ data.impulse_joint_set.remove(child.connection, true);
+ }
+ player.children[slot as usize] = None;
+ }
+ Entity::AttachedModule(ref mut module) => {
+ if let Some(child) = &module.children[slot as usize] {
+ data.impulse_joint_set.remove(child.connection, true);
+ }
+ module.children[slot as usize] = None;
+ }
+ _ => {
+ panic!("unexpected parent");
+ }
+ };
+ // remove joint
+ let tree = module.search_modules(entities);
+ let new_module = Module {
+ handle: module.handle,
+ module_type: module.module_type,
+ lifetime: 0.,
+ flags: 0,
+ };
+ entity_map.remove(&entities.get_id_from_attached(module.clone()).unwrap());
+ let id = get_entity_id();
+ entity_map.insert(id, Entity::Module(new_module));
+ for element in tree {
+ for child in element.clone().children {
+ if let Some(child) = child {
+ debug!("child: {:?}", child);
+ data.impulse_joint_set.remove(child.connection, true);
+ let child_body = entities.get_attached_from_id(child.child).unwrap();
+ let new_module = Module {
+ handle: child_body.handle,
+ module_type: child_body.module_type,
+ lifetime: 0.,
+ flags: 0,
+ };
+ entity_map.remove(&entities.get_id_from_attached(child_body.clone()).unwrap());
+ let attached_id = get_entity_id();
+ entity_map.insert(attached_id, Entity::Module(new_module));
+ }
+ }
+ }
+ entities.entities = entity_map;
+ id
+ }
pub fn attach_new(
data: &mut PhysicsData,
entities: &mut EntityHandler,
@@ 320,9 385,30 @@ impl AttachedModule {
}
modules
}
+
+ pub fn find_parent(&self, module: AttachedModule, entities: &EntityHandler) -> Option<(u8, EntityId)> {
+ for (slot, attachment) in self.children.iter().enumerate() {
+ if let Some(attachment) = attachment {
+ if let Entity::AttachedModule(child_module) =
+ entities.entities.get(&attachment.child).unwrap()
+ {
+ debug!("child: {:?}", *child_module);
+ debug!("target: {:?}", module);
+ if *child_module == module {
+ return Some((slot as u8, entities.get_id_from_attached(self.clone()).unwrap()));
+ }
+ let parent = child_module.find_parent(module.clone(), entities);
+ if let Some(_) = parent {
+ return parent;
+ }
+ }
+ }
+ }
+ None
+ }
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
pub struct Attachment {
pub child: EntityId,
pub connection: ImpulseJointHandle,
M server/src/planet.rs => server/src/planet.rs +1 -1
@@ 15,7 15,7 @@ use crate::{manager::ClientHandlerMessage, SCALE};
pub const GRAVITY: f64 = 0.02;
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct Planet {
pub planet_type: PlanetType,
pub body_handle: RigidBodyHandle,