mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Load more config data from files (instead of hardcoded)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1797,6 +1797,7 @@ dependencies = [
|
||||
"polariton",
|
||||
"polariton_auth",
|
||||
"polariton_server",
|
||||
"rand 0.9.0",
|
||||
"rc_core",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -14415,5 +14415,65 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"banners": [
|
||||
{
|
||||
"message": "No jam was harmed in the reverse-engineering of this game",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Struggling to open jars since 2013",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "If you can read this, you've benefitted from an education department!",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Support your local minorities",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "\u0421\u043b\u0430\u0432\u0430 \u0423\u043a\u0440\u0430\u0457\u043d\u0456! Slava Ukraini!",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Now with more poutine",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Free Palestine!",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Hacker free",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Hey cutie",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Tesla Coils are the only useful Teslas",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Welcome to OpenJam's servers",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Made in sovereign Canada",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Finally, how to craft Robo",
|
||||
"duration": 20
|
||||
},
|
||||
{
|
||||
"message": "Warning, live without warning\nI say, warning, live without warning\nWithout, all right",
|
||||
"duration": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ pub struct GameplaySettings {
|
||||
}
|
||||
|
||||
impl GameplaySettings {
|
||||
pub fn as_transmissible(&self) -> Typed {
|
||||
pub fn as_transmissible<C>(&self) -> Typed<C> {
|
||||
Typed::HashMap(vec![
|
||||
// TODO
|
||||
(Typed::Str("showTutorialAfterDate".into()), Typed::Str(self.show_tutorial_after_date.clone().into())),
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod auto_regen;
|
||||
pub mod campaign;
|
||||
pub mod client_config;
|
||||
pub mod cube_list;
|
||||
pub mod game_mode;
|
||||
pub mod garage_bay;
|
||||
|
||||
32
rc_core/src/persist/client_config.rs
Normal file
32
rc_core/src/persist/client_config.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct GameplaySettings {
|
||||
pub show_tutorial_after_date: String,
|
||||
pub health_threshold: f32, // percent
|
||||
pub microbot_sphere: f32, // radius
|
||||
pub misfire_angle: f32, // degrees?
|
||||
pub shield_dps: i32,
|
||||
pub shield_hps: u32,
|
||||
pub request_review_level: u32,
|
||||
pub critical_ratio: f32,
|
||||
pub cross_promo_image: String, // url
|
||||
pub cross_promo_link: String, // url
|
||||
}
|
||||
|
||||
impl std::convert::Into<crate::data::client_config::GameplaySettings> for GameplaySettings {
|
||||
fn into(self) -> crate::data::client_config::GameplaySettings {
|
||||
crate::data::client_config::GameplaySettings {
|
||||
show_tutorial_after_date: self.show_tutorial_after_date,
|
||||
health_threshold: self.health_threshold,
|
||||
microbot_sphere: self.microbot_sphere,
|
||||
misfire_angle: self.misfire_angle,
|
||||
shield_dps: self.shield_dps,
|
||||
shield_hps: self.shield_hps,
|
||||
request_review_level: self.request_review_level,
|
||||
critical_ratio: self.critical_ratio,
|
||||
cross_promo_image: self.cross_promo_image,
|
||||
cross_promo_link: self.cross_promo_link,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ use serde::{Serialize, Deserialize};
|
||||
use polariton::operation::{Typed, Dict};
|
||||
use polariton::serdes::TypePrefix;
|
||||
|
||||
use super::super::{MovementCategoryData, MovementData, Cube, ItemCategory, ItemTier, BattleConfig};
|
||||
use super::super::{MovementCategoryData, MovementData, Cube, ItemCategory, ItemTier, BattleConfig, Settings};
|
||||
|
||||
const CUBE_CONFIG_FILENAME: &str = "config.json";
|
||||
|
||||
@@ -15,6 +15,7 @@ pub struct CubeConfig {
|
||||
movement: HashMap<ItemCategory, MovementCategoryData>,
|
||||
lerp_value: f32,
|
||||
battle: BattleConfig,
|
||||
settings: Settings,
|
||||
}
|
||||
|
||||
impl CubeConfig {
|
||||
@@ -231,4 +232,19 @@ impl <C: Clone> super::ConfigProvider<C> for CubeConfig {
|
||||
}
|
||||
super::CompleteCampaignProvider::new(map)
|
||||
}
|
||||
|
||||
fn client_config(&self) -> Typed<C> {
|
||||
let conf_data: crate::data::client_config::GameplaySettings = self.settings.gameplay.clone().into();
|
||||
Typed::Dict(Dict {
|
||||
key_ty: TypePrefix::Str,
|
||||
val_ty: TypePrefix::HashMap,
|
||||
items: vec![
|
||||
(Typed::Str("GameplaySettings".into()), conf_data.as_transmissible()),
|
||||
].into(),
|
||||
})
|
||||
}
|
||||
|
||||
fn login_messages(&self) -> super::DevMessageProvider<C> {
|
||||
super::DevMessageProvider::new(self.settings.banners.iter().map(|msg| (msg.message.clone(), msg.duration as i32)).collect())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ mod cubes_json;
|
||||
pub use cubes_json::CubeConfig;
|
||||
|
||||
mod traits;
|
||||
pub use traits::{ConfigProvider, CompleteCampaignProvider};
|
||||
pub use traits::{ConfigProvider, CompleteCampaignProvider, DevMessageProvider};
|
||||
|
||||
pub type ConfigImpl = CubeConfig;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use polariton::operation::Typed;
|
||||
|
||||
pub trait ConfigProvider<C> {
|
||||
pub trait ConfigProvider<C: Clone> {
|
||||
fn cube_list(&self) -> Typed<C>;
|
||||
fn movement_list(&self) -> Typed<C>;
|
||||
fn weapon_list(&self) -> Typed<C>;
|
||||
@@ -15,6 +15,8 @@ pub trait ConfigProvider<C> {
|
||||
fn campaign_waves(&self) -> Typed<C>;
|
||||
fn campaign_version(&self) -> Typed<C>;
|
||||
fn campaign_details(&self) -> CompleteCampaignProvider;
|
||||
fn client_config(&self) -> Typed<C>;
|
||||
fn login_messages(&self) -> DevMessageProvider<C>;
|
||||
}
|
||||
|
||||
pub struct CompleteCampaignProvider {
|
||||
@@ -40,3 +42,43 @@ impl CompleteCampaignProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DevMessageProvider<C: Clone> {
|
||||
messages: Vec<TypedDevMessage<C>>,
|
||||
}
|
||||
|
||||
impl <C: Clone> DevMessageProvider<C> {
|
||||
pub fn new(messages: Vec<(String, i32)>) -> Self {
|
||||
Self {
|
||||
messages: messages.into_iter().map(|(msg, time)| {
|
||||
let bytes: Vec<u8> = msg.as_bytes().into();
|
||||
TypedDevMessage {
|
||||
message: Typed::Bytes(bytes.into()),
|
||||
display_time: Typed::Int(time),
|
||||
}
|
||||
}
|
||||
).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, index: usize) -> TypedDevMessage<C> {
|
||||
// TODO maybe make this less obtuse -- it works for random, but isn't really obvious for anything else
|
||||
if self.messages.is_empty() {
|
||||
TypedDevMessage {
|
||||
message: Typed::Bytes(Vec::default().into()),
|
||||
display_time: Typed::Int(-1),
|
||||
}
|
||||
} else if self.messages.len() == 1 {
|
||||
self.messages[0].clone()
|
||||
} else {
|
||||
let actual_index = index % self.messages.len(); // guarantees index is within allowed range of messages
|
||||
self.messages[actual_index].clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TypedDevMessage<C> {
|
||||
pub message: Typed<C>,
|
||||
pub display_time: Typed<C>,
|
||||
}
|
||||
|
||||
@@ -23,7 +23,11 @@ pub use combat::BattleConfig;
|
||||
mod singleplayer;
|
||||
pub use singleplayer::{Campaigns, Campaign, CampaignDifficulty, CampaignCompletion, CampaignType, Wave, WaveRobot};
|
||||
|
||||
// TODO put this in core lib
|
||||
mod client_config;
|
||||
pub use client_config::GameplaySettings;
|
||||
|
||||
mod settings;
|
||||
pub use settings::Settings;
|
||||
|
||||
pub(self) const VALID_ROBOT: &[u8] = &[64,
|
||||
0,
|
||||
|
||||
34
rc_core/src/persist/settings.rs
Normal file
34
rc_core/src/persist/settings.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct Settings {
|
||||
#[serde(default = "default_gameplay_settings")]
|
||||
pub gameplay: super::GameplaySettings,
|
||||
#[serde(default = "default_dev_messages")]
|
||||
pub banners: Vec<BannerMessage>,
|
||||
}
|
||||
|
||||
fn default_gameplay_settings() -> super::GameplaySettings {
|
||||
super::GameplaySettings {
|
||||
show_tutorial_after_date: "2030-01-01".to_owned(),
|
||||
health_threshold: 0.20,
|
||||
microbot_sphere: 10.0,
|
||||
misfire_angle: 10.0,
|
||||
shield_dps: 100,
|
||||
shield_hps: 2_000,
|
||||
request_review_level: 10_000,
|
||||
critical_ratio: 5.0,
|
||||
cross_promo_image: "https://git.ngram.ca/assets/img/logo.png".to_owned(),
|
||||
cross_promo_link: "https://git.ngram.ca/OpenJam/servers".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct BannerMessage {
|
||||
pub message: String,
|
||||
pub duration: u32, // seconds
|
||||
}
|
||||
|
||||
fn default_dev_messages() -> Vec<BannerMessage> {
|
||||
Vec::default()
|
||||
}
|
||||
@@ -17,3 +17,4 @@ serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
chrono = "0.4"
|
||||
rc_core = { version = "*", path = "../rc_core" }
|
||||
rand = "0.9"
|
||||
|
||||
@@ -2,7 +2,7 @@ pub use rc_core::data::cube_list;
|
||||
pub mod special_item;
|
||||
pub mod premium_config;
|
||||
pub mod palette;
|
||||
pub mod client_config;
|
||||
//pub mod client_config;
|
||||
pub mod crf_config;
|
||||
pub use rc_core::data::weapon_list;
|
||||
//pub use rc_core::data::movement_list;
|
||||
|
||||
@@ -1,31 +1,14 @@
|
||||
use polariton_server::operations::SimpleFunc;
|
||||
use polariton::{operation::{Dict, ParameterTable, Typed}, serdes::TypePrefix};
|
||||
|
||||
use crate::data::client_config::*;
|
||||
use polariton_server::operations::Immediate;
|
||||
//use polariton::{operation::{Dict, ParameterTable, Typed}, serdes::TypePrefix};
|
||||
use rc_core::ConfigProvider;
|
||||
|
||||
const PARAM_KEY: u8 = 36;
|
||||
|
||||
pub(super) fn client_config_provider() -> SimpleFunc<34, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
|
||||
SimpleFunc::new(|params, _| {
|
||||
let mut params = params.to_dict();
|
||||
params.insert(PARAM_KEY, Typed::Dict(Dict {
|
||||
key_ty: TypePrefix::Str, // str
|
||||
val_ty: TypePrefix::HashMap, // hashtable
|
||||
items: vec![
|
||||
(Typed::Str("GameplaySettings".into()), GameplaySettings {
|
||||
show_tutorial_after_date: "2030-01-01".to_owned(),
|
||||
health_threshold: 0.20,
|
||||
microbot_sphere: 10.0,
|
||||
misfire_angle: 10.0,
|
||||
shield_dps: 100,
|
||||
shield_hps: 2_000,
|
||||
request_review_level: 10_000,
|
||||
critical_ratio: 5.0,
|
||||
cross_promo_image: "https://git.ngram.ca/assets/img/logo.png".to_owned(),
|
||||
cross_promo_link: "https://git.ngram.ca/OpenJam/servers".to_owned(),
|
||||
}.as_transmissible())
|
||||
].into(),
|
||||
}));
|
||||
Ok(params.into())
|
||||
pub(super) fn client_config_provider(conf: &rc_core::ConfigImpl) -> Immediate<34, crate::UserTy> {
|
||||
let client_conf = conf.client_config();
|
||||
Immediate::new(|| {
|
||||
let mut params = std::collections::HashMap::with_capacity(1);
|
||||
params.insert(PARAM_KEY, client_conf.clone());
|
||||
params.into()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
use polariton_server::operations::SimpleFunc;
|
||||
use polariton::operation::{ParameterTable, Typed};
|
||||
use polariton::operation::ParameterTable;
|
||||
use rand::Rng;
|
||||
use rc_core::ConfigProvider;
|
||||
|
||||
const MESSAGE_PARAM_KEY: u8 = 2;
|
||||
const DISPLAY_TIME_PARAM_KEY: u8 = 15;
|
||||
|
||||
pub(super) fn dev_message_provider() -> SimpleFunc<8, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
|
||||
SimpleFunc::new(|params, _| {
|
||||
pub(super) fn dev_message_provider(conf: &rc_core::ConfigImpl) -> SimpleFunc<8, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
|
||||
let messages = conf.login_messages();
|
||||
SimpleFunc::new(move |params, _| {
|
||||
let mut params = params.to_dict();
|
||||
params.insert(MESSAGE_PARAM_KEY, Typed::Bytes(Vec::from("No jam was harmed in the reverse-engineering of this game".as_bytes()).into()));
|
||||
params.insert(DISPLAY_TIME_PARAM_KEY, Typed::Int(60 /* seconds??? */));
|
||||
let index = rand::rng().random::<u32>();
|
||||
let dev_msg = messages.get(index as _);
|
||||
params.insert(MESSAGE_PARAM_KEY, dev_msg.message);
|
||||
params.insert(DISPLAY_TIME_PARAM_KEY, dev_msg.display_time);
|
||||
Ok(params.into())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ impl <C> Operation<C> for UserFlagsTeller {
|
||||
let mut resp_params = std::collections::HashMap::new();
|
||||
resp_params.insert(Self::REMOVE_OBSOLETE_CUBES_KEY, polariton::operation::Typed::Bool(false.into()));
|
||||
resp_params.insert(Self::REMOVE_UNOWNED_CUBES_KEY, polariton::operation::Typed::Bool(false.into()));
|
||||
resp_params.insert(Self::REWARD_TITLE_KEY, polariton::operation::Typed::Str("Yay a reward!".into()));
|
||||
resp_params.insert(Self::REWARD_BODY_KEY, polariton::operation::Typed::Str("I love you very much so here's nothing as a reward.".into()));
|
||||
resp_params.insert(Self::REWARD_TITLE_KEY, polariton::operation::Typed::Str("".into()));
|
||||
resp_params.insert(Self::REWARD_BODY_KEY, polariton::operation::Typed::Str("".into())); // set this to non-empty to display pop-up at login
|
||||
resp_params.insert(Self::REFUND_OBSOLETE_CUBES_KEY, polariton::operation::Typed::Bool(false.into()));
|
||||
resp_params.insert(Self::CUBES_ARE_REPLACED_KEY, polariton::operation::Typed::Bool(false.into()));
|
||||
resp_params.insert(Self::NEW_USER_KEY, polariton::operation::Typed::Bool(false.into()));
|
||||
|
||||
@@ -100,7 +100,7 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
|
||||
.without_state(special_items::special_item_list_provider())
|
||||
.without_state(premium_config::premium_config_provider())
|
||||
.without_state(palette_town::kanto())
|
||||
.without_state(client_config::client_config_provider())
|
||||
.without_state(client_config::client_config_provider(&init_ctx.cubes))
|
||||
.without_state(crf_config::crf_config_provider())
|
||||
.without_state(weapon_stats::weapon_config_provider(&init_ctx.cubes))
|
||||
.without_state(movement_stats::movement_config_provider(&init_ctx.cubes))
|
||||
@@ -122,7 +122,7 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
|
||||
.without_state(robopass_season::robopass_season_provider())
|
||||
.without_state(owned_cosmetics::owned_cosmetics_provider())
|
||||
.without_state(owned_cosmetics::selected_cosmetics_provider())
|
||||
.without_state(dev_message::dev_message_provider())
|
||||
.without_state(dev_message::dev_message_provider(&init_ctx.cubes))
|
||||
.without_state(custom_games_maps::allowed_maps_provider())
|
||||
.without_state(avatar_info::get_avatar_provider())
|
||||
.without_state(custom_game_session::get_custom_session_provider())
|
||||
|
||||
@@ -174,6 +174,23 @@ CATEGORIES_PLACEMENTS = {
|
||||
"EnergyModule": ALL_FACES,
|
||||
}
|
||||
|
||||
LOGIN_MESSAGES = [
|
||||
"No jam was harmed in the reverse-engineering of this game",
|
||||
"Struggling to open jars since 2013",
|
||||
"If you can read this, you've benefitted from an education department!",
|
||||
"Support your local minorities",
|
||||
"Слава Україні! Slava Ukraini!",
|
||||
"Now with more poutine",
|
||||
"Free Palestine!",
|
||||
"Hacker free",
|
||||
"Hey cutie",
|
||||
"Tesla Coils are the only useful Teslas",
|
||||
"Welcome to OpenJam's servers",
|
||||
"Made in sovereign Canada",
|
||||
"Finally, how to craft Robo",
|
||||
"Warning, live without warning\nI say, warning, live without warning\nWithout, all right",
|
||||
]
|
||||
|
||||
def guess_category(name: str, sprite: str) -> str:
|
||||
name = name.lower()
|
||||
sprite = sprite.lower()
|
||||
@@ -427,7 +444,13 @@ def main(asset_in, cubes=None, weapons=None, movement=None):
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"banners": [{
|
||||
"message": msg,
|
||||
"duration": 20,
|
||||
} for msg in LOGIN_MESSAGES],
|
||||
},
|
||||
}
|
||||
last_tech_tree_id = 0
|
||||
tech_tree_index = 0
|
||||
|
||||
Reference in New Issue
Block a user