@@ 1,4 1,3 @@
-use std::f32::consts::PI;
// StarKingdoms.IO, a browser game about drifting through space
// Copyright (C) 2023 ghostly_zsh, TerraMaster85, core
//
@@ 28,6 27,7 @@ use component::*;
use packet::*;
use rand::Rng;
use starkingdoms_common::unpack_savefile;
+use std::f32::consts::PI;
pub mod component;
pub mod macros;
@@ 81,7 81,10 @@ fn main() {
.add_systems(Update, on_message)
.add_systems(Update, on_close)
.add_systems(FixedUpdate, on_position_change)
- .add_systems(FixedUpdate, (gravity_update, player_input_update).chain())
+ .add_systems(
+ FixedUpdate,
+ (break_modules, gravity_update, player_input_update).chain(),
+ )
.add_systems(FixedUpdate, convert_modules)
//.insert_resource(Time::<Fixed>::from_seconds(1.0/20.0))
.run();
@@ 180,6 183,11 @@ fn module_spawn(
0.,
)));
})
+ .insert(AdditionalMassProperties::MassProperties(MassProperties {
+ local_center_of_mass: vec2(0.0, 0.0),
+ mass: 0.0001,
+ principal_inertia: 0.005,
+ }))
.insert(ExternalForce::default())
.insert(ExternalImpulse::default())
.insert(Velocity::default())
@@ 505,7 513,7 @@ fn on_message(
commands
.entity(loose_attach.children[2].unwrap())
.insert(Attach {
- associated_player: attach.associated_player,
+ associated_player: Some(entity),
parent: Some(entity),
children: [None, None, None, None],
});
@@ 558,7 566,7 @@ fn on_message(
commands
.entity(loose_attach.children[2].unwrap())
.insert(Attach {
- associated_player: attach.associated_player,
+ associated_player: Some(entity),
parent: Some(entity),
children: [None, None, None, None],
});
@@ 616,7 624,7 @@ fn on_message(
commands
.entity(loose_attach.children[2].unwrap())
.insert(Attach {
- associated_player: attach.associated_player,
+ associated_player: Some(entity),
parent: Some(entity),
children: [None, None, None, None],
});
@@ 678,7 686,7 @@ fn on_message(
commands
.entity(loose_attach.children[2].unwrap())
.insert(Attach {
- associated_player: attach.associated_player,
+ associated_player: Some(entity),
parent: Some(entity),
children: [None, None, None, None],
});
@@ 1256,6 1264,11 @@ fn convert_modules_recursive(
.insert(ExternalImpulse::default())
.insert(Velocity::default())
.insert(ReadMassProperties::default())
+ .insert(AdditionalMassProperties::MassProperties(MassProperties {
+ local_center_of_mass: vec2(0.0, 0.0),
+ mass: 0.00000000000001,
+ principal_inertia: 0.0000000000001,
+ }))
.insert(Attach {
associated_player: attach.associated_player,
parent: Some(module_entity),
@@ 1305,6 1318,72 @@ fn convert_modules_recursive(
}
}
+fn break_modules(
+ mut commands: Commands,
+ rapier_context: Res<RapierContext>,
+ mut attached_query: Query<
+ (
+ Entity,
+ &PartType,
+ &mut Transform,
+ &mut Attach,
+ &Velocity,
+ Option<&CanAttach>,
+ Option<&LooseAttach>,
+ ),
+ (Without<PlanetType>, Without<Player>),
+ >,
+ mut player_query: Query<&mut Attach, With<Player>>,
+) {
+ let joints = rapier_context.entity2impulse_joint();
+ let mut detach_list = Vec::new();
+ for (entity, part_type, _, attach, _, _, _) in &mut attached_query {
+ if *part_type == PartType::LandingThrusterSuspension {
+ continue;
+ }
+ let handle = joints.get(&entity).unwrap();
+ let joint = rapier_context.impulse_joints.get(*handle).unwrap();
+ if joint.impulses.magnitude() > 0.00005 {
+ detach_list.push((entity, *part_type, attach.clone()));
+ }
+ }
+ for (entity, part_type, attach) in detach_list {
+ commands.entity(entity).remove::<ImpulseJoint>();
+ commands.entity(entity).remove::<Attach>();
+ if part_type == PartType::LandingThruster {
+ commands.entity(entity).insert(LooseAttach {
+ children: attach.children,
+ });
+ commands
+ .entity(attach.children[2].unwrap())
+ .remove::<Attach>();
+ } else {
+ detach_recursive(&mut commands, attach.clone(), &mut attached_query);
+ }
+ let parent = attach.parent.unwrap();
+ if attached_query.contains(parent) {
+ let mut parent_attach = attached_query.get_mut(parent).unwrap().3;
+ let children = parent_attach.children.clone();
+ for (i, child) in children.iter().enumerate() {
+ if let Some(child) = child {
+ if *child == entity {
+ parent_attach.children[i] = None;
+ }
+ }
+ }
+ } else {
+ let mut attach = player_query.get_mut(parent).unwrap();
+ for (i, child) in attach.children.clone().iter().enumerate() {
+ if let Some(child) = child {
+ if *child == entity {
+ attach.children[i] = None;
+ }
+ }
+ }
+ }
+ }
+}
+
fn on_close(
player_query: Query<(Entity, &Player, &Attach)>,
attached_query: Query<&Attach, With<PartType>>,
@@ 4,6 4,7 @@
import ChevronDown from "../../icons/ChevronDown.svelte";
import ChevronUp from "../../icons/ChevronUp.svelte";
import Button from "./Button.svelte";
import createDebug from "debug";
let clazz = "";
export { clazz as class };
@@ 28,11 29,17 @@
onMount(() => {
if (draggable) {
let top = window.localStorage.getItem(`pop-${id}top`);
let left = window.localStorage.getItem(`pop-${id}left`);
pos1 = parseInt(window.localStorage.getItem(`pop-${id}top`));
pos2 = parseInt(window.localStorage.getItem(`pop-${id}left`));
popup.style.top = top;
popup.style.left = left;
// Correct illegally placed draggables
// Disabled until I can find a nice way to run this after the dynamic
// content injection by svelte
//[pos1, pos2] = dragBoundsEnforce();
// I hate JS for letting me pull crap like this
popup.style.top = `${pos1}px`;
popup.style.left = `${pos2}px`;
}
if (minimizable) {
minimized = window.localStorage.getItem(`pop-${id}minim`) === "yes";
@@ 43,23 50,67 @@
if (!draggable) {
return;
}
pos3 = e.clientX;
pos4 = e.clientY;
let popup_dimensions = popup.getBoundingClientRect();
pos3 = e.clientX - popup_dimensions.left;
pos4 = e.clientY - popup_dimensions.top;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e.preventDefault();
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
popup.style.top = popup.offsetTop - pos2 + "px";
popup.style.left = popup.offsetLeft - pos1 + "px";
window.localStorage.setItem(`pop-${id}top`, popup.style.top);
window.localStorage.setItem(`pop-${id}left`, popup.style.left);
pos1 = e.clientX - pos3;
pos2 = e.clientY - pos4;
let [left, top, bounds_violated] = dragBoundsEnforce();
popup.style.left = left + "px";
popup.style.top = top + "px";
}
function dragBoundsEnforce() {
let left = pos1;
let top = pos2;
let popup_dimensions = popup.getBoundingClientRect();
// This was originally meant to specify the amount of error acceptable
// before snapping to an edge or corner, but now it seems to merely adjust
// the amount of pixels between the screen edge and the bounds.
let snap_distance = 16;
let bounds = {
top: 8 + snap_distance,
left: 8 + snap_distance,
bottom: window.innerHeight - popup_dimensions.height - 8 - snap_distance,
right: window.innerWidth - popup_dimensions.width - 8 - snap_distance,
};
let bounds_violated = false;
// Add cases for snapping here
if (left >= bounds.right) {
// Too far right!
left = bounds.right;
bounds_violated = true;
} else if (left <= bounds.left) {
// Too far left!
left = bounds.left;
bounds_violated = true;
}
if (top >= bounds.bottom) {
// Too far down!
top = bounds.bottom;
bounds_violated = true;
} else if (top <= bounds.top) {
// Too far up!
top = bounds.top;
bounds_violated = true;
}
return [left, top, bounds_violated];
}
function closeDragElement() {
@@ 4,14 4,45 @@
</script>
<svg
+ width="1rem"
+ height="1rem"
+ viewBox="0 0 32 32"
+ version="1.1"
+ id="svg1"
xmlns="http://www.w3.org/2000/svg"
- fill="none"
- viewBox="0 0 24 24"
- stroke-width="1.5"
- stroke="currentColor"
- class={clazz}>
- <path
- stroke-linecap="round"
- stroke-linejoin="round"
- d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" />
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs id="defs1" />
+ <g id="layer1">
+ <path
+ id="rect1-5"
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0"
+ d="M 6,22 0,16 6,10 Z" />
+ <path
+ id="rect1-5-6"
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0"
+ d="M 10,6 16,0 22,6 Z" />
+ <path
+ id="rect1-5-61"
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0"
+ d="M 26,10 32,16 26,22 Z" />
+ <path
+ id="rect1-5-2"
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0"
+ d="M 22,26 16,32 10,26 Z" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0"
+ id="rect1"
+ width="4"
+ height="24"
+ x="14"
+ y="4" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke-width:0"
+ id="rect1-7"
+ width="4"
+ height="24"
+ x="14"
+ y="-28"
+ transform="rotate(90)" />
+ </g>
</svg>