1
Fork 0
mirror of https://github.com/RGBCube/ManageTTD synced 2025-07-29 09:57:47 +00:00

Chore: Make stuff work

This commit is contained in:
RGBCube 2023-03-18 23:09:21 +03:00
parent 9cf8db8f17
commit 185789c9d5
8 changed files with 176 additions and 91 deletions

View file

@ -1,7 +1,5 @@
module config module config
import config.mapping
pub enum ConfigType { pub enum ConfigType {
openttd openttd
private private
@ -10,10 +8,10 @@ pub enum ConfigType {
// because they are not useful for dedicated servers. // because they are not useful for dedicated servers.
} }
fn (ct ConfigType) mapping() mapping.Mapping { pub fn (ct ConfigType) mapping() Mapping {
return match ct { return match ct {
.openttd { mapping.openttd_config } .openttd { openttd_config_mapping }
.private { mapping.private_config } .secrets { secrets_config_mapping }
.secrets { mapping.secrets_config } .private { private_config_mapping }
} }
} }

View file

@ -1,6 +1,23 @@
module config module config
import strings import strings
import toml
fn nested_string_map_to_toml(m map[string]map[string]string) string {
mut toml_string := strings.new_builder(12800)
for section, fields in m {
toml_string.writeln('[${section}]')
for field, value in fields {
toml_string.writeln('${field} = ${value}')
}
toml_string.write_rune(`\n`)
}
return toml_string.str()
}
[noinit] [noinit]
pub struct OpenTTDConfig { pub struct OpenTTDConfig {
@ -9,17 +26,16 @@ pub struct OpenTTDConfig {
} }
pub fn (oc OpenTTDConfig) str() string { pub fn (oc OpenTTDConfig) str() string {
mut config_string := strings.new_builder(12800) return nested_string_map_to_toml(oc.content)
for section, section_content in oc.content {
config_string.write_string('[${section}]\n')
for field, value in section_content {
config_string.write_string('${field} = ${value}\n')
}
} }
return config_string.str() pub fn managettd_config_from_file(path string, @type ConfigType) !ManageTTDConfig {
config_toml := toml.parse_file(path)!
return ManageTTDConfig{
content: config_toml.reflect[map[string]map[string]string]()
@type: @type
}
} }
pub struct ManageTTDConfig { pub struct ManageTTDConfig {
@ -27,16 +43,20 @@ pub struct ManageTTDConfig {
@type ConfigType @type ConfigType
} }
pub fn (mc ManageTTDConfig) str() string {
return nested_string_map_to_toml(mc.content)
}
// TODO: validate values. // TODO: validate values.
pub fn (mc ManageTTDConfig) validate() ! { pub fn (mc ManageTTDConfig) validate() ! {
mapping := mc.@type.mapping() mapping := mc.@type.mapping()
for section, section_content in mc.content { for section, fields in mc.content {
if section !in mapping { if section !in mapping {
return error('Invalid section: ${section}') return error('Invalid section: ${section}')
} }
for field, _ in section_content { for field, _ in fields {
if field !in mapping[section] { if field !in mapping[section] {
return error('Invalid key: ${field}') return error('Invalid key: ${field}')
} }
@ -49,20 +69,20 @@ pub fn (mc ManageTTDConfig) to_openttd_config() !OpenTTDConfig {
mapping := mc.@type.mapping() mapping := mc.@type.mapping()
mut openttd_config := map[string]map[string]string{} mut config := map[string]map[string]string{}
for section, section_content in mc.content { for section, fields in mc.content {
section_mapping := mapping[section] section_mapping := mapping[section].clone()
for field, value in section_content { for field, value in fields {
key_mapping := section_mapping[field] key_mapping := section_mapping[field]
openttd_config[key_mapping.section()][key_mapping.field()] = key_mapping.transform(value) config[key_mapping.section()][key_mapping.field()] = key_mapping.transform(value)
} }
} }
return OpenTTDConfig{ return OpenTTDConfig{
content: openttd_config content: config
@type: mc.@type @type: mc.@type
} }
} }

73
src/config/mapping.v Normal file
View file

@ -0,0 +1,73 @@
module config
import strings
pub type Mapping = map[string]map[string]Map
pub fn (m Mapping) str() string {
mut mapping_string := strings.new_builder(12800)
for section, fields in m {
mapping_string.writeln('[${section}]')
for field, field_value in fields {
mapping_string.writeln('${field} = ${field_value.transformed_default_value()}}')
}
mapping_string.write_rune(`\n`)
}
return mapping_string.str()
}
pub fn (m Mapping) to_openttd_config(@type ConfigType) OpenTTDConfig {
return m.to_managettd_config(@type).to_openttd_config() or { panic('unreachable') }
}
pub fn (m Mapping) to_managettd_config(@type ConfigType) ManageTTDConfig {
mut config_map := map[string]map[string]string{}
for section, fields in m {
config_map[section] = map[string]string{}
for field, field_value in fields {
config_map[section][field] = field_value.transformed_default_value()
}
}
return ManageTTDConfig{
content: config_map
@type: @type
}
}
[noinit]
pub struct Map {
equivalent []string [required]
documentation string [required]
default_value string [required]
transform fn (string) string = fn (s string) string {
return s
}
}
pub fn (m Map) str() string {
comment := '; ' + m.documentation.split_into_lines().join('; ')
field := m.field()
value := m.transformed_default_value()
return '${comment}\n${field} = ${value}'
}
pub fn (m Map) section() string {
return m.equivalent[0]
}
pub fn (m Map) field() string {
return m.equivalent[1]
}
pub fn (m Map) transformed_default_value() string {
return m.transform(m.default_value)
}

View file

@ -1,54 +0,0 @@
module mapping
import config
pub type Mapping = map[string]map[string]Map
pub fn (m Mapping) to_managettd_config() config.ManageTTDConfig {
mut config_map := map[string]map[string]string{}
for section, fields in m {
config_map[section] = map[string]string{}
for field, map in fields {
config_map[section][field] = map.transformed_default_value()
}
}
return config.ManageTTDConfig{
content: config_map
@type: // TODO
}
}
[noinit]
pub struct Map {
equivalent []string [required]
documentation string [required]
default_value string [required]
pub:
transform fn (string) string = fn (s string) string {
return s
}
}
pub fn (m Map) section() string {
return m.equivalent[0]
}
pub fn (m Map) field() string {
return m.equivalent[1]
}
pub fn (m Map) transformed_default_value() string {
return m.transform(m.default_value)
}
pub fn (m Map) str() string {
comment := '; ' + m.documentation.split_into_lines().join('; ')
field := m.field()
value := m.transformed_default_value()
return '${comment}\n${field} = ${value}'
}

View file

@ -1,33 +1,33 @@
module mapping module config
pub const openttd_config = Mapping({ pub const openttd_config_mapping = Mapping({
'ratelimits': { 'ratelimits': {
'maximum_initialization_time': Map{ 'maximum_initialization_time': Map{
equivalent: 'network.max_init_time' equivalent: ['network', 'max_init_time']
documentation: 'The time the client has to initialize the game in seconds.' documentation: 'The time the client has to initialize the game in seconds.'
default_value: '5' default_value: '5'
transform: seconds_to_ticks transform: seconds_to_ticks
} }
'maximum_join_time': Map{ 'maximum_join_time': Map{
equivalent: 'network.max_join_time' equivalent: ['network', 'max_join_time']
documentation: 'The time the client has to join the server in seconds.' documentation: 'The time the client has to join the server in seconds.'
default_value: '20' default_value: '20'
transform: seconds_to_ticks transform: seconds_to_ticks
} }
'maximum_download_time': Map{ 'maximum_download_time': Map{
equivalent: 'network.max_download_time' equivalent: ['network', 'max_download_time']
documentation: 'The time the client has to download the map in seconds.' documentation: 'The time the client has to download the map in seconds.'
default_value: '300' default_value: '300'
transform: seconds_to_ticks transform: seconds_to_ticks
} }
'maximum_password_time': Map{ 'maximum_password_time': Map{
equivalent: 'network.max_password_time' equivalent: ['network', 'max_password_time']
documentation: 'The time the client has to enter the server password in seconds.' documentation: 'The time the client has to enter the server password in seconds.'
default_value: '600' default_value: '600'
transform: seconds_to_ticks transform: seconds_to_ticks
} }
'maximum_lag_time': Map{ 'maximum_lag_time': Map{
equivalent: 'network.max_lag_time' equivalent: ['network', 'max_lag_time']
documentation: 'The time the client can lag behind the server in seconds.' documentation: 'The time the client can lag behind the server in seconds.'
default_value: '20' default_value: '20'
transform: seconds_to_ticks transform: seconds_to_ticks
@ -35,7 +35,7 @@ pub const openttd_config = Mapping({
} }
'server': { 'server': {
'is_public': Map{ 'is_public': Map{
equivalent: 'network.server_game_type' equivalent: ['network', 'server_game_type']
documentation: 'Whether if the server is public. True means the server can be joined from the server list.' documentation: 'Whether if the server is public. True means the server can be joined from the server list.'
default_value: 'true' default_value: 'true'
transform: boolean_to_custom_value(['private', 'public']) transform: boolean_to_custom_value(['private', 'public'])
@ -43,7 +43,7 @@ pub const openttd_config = Mapping({
} }
'autoclean': { 'autoclean': {
'enabled': Map{ 'enabled': Map{
equivalent: 'network.autoclean_companies' equivalent: ['network', 'autoclean_companies']
documentation: 'Whether if the server should automatically clean up companies. documentation: 'Whether if the server should automatically clean up companies.
Other autoclean settings only have effect if this is set to true.' Other autoclean settings only have effect if this is set to true.'
default_value: 'false' default_value: 'false'
@ -51,6 +51,6 @@ Other autoclean settings only have effect if this is set to true.'
} }
}) })
pub const private_config = Mapping{} pub const private_config_mapping = Mapping(map[string]map[string]Map{})
pub const secrets_config = Mapping{} pub const secrets_config_mapping = Mapping(map[string]map[string]Map{})

View file

@ -1,4 +1,4 @@
module mapping module config
fn seconds_to_ticks(s string) string { fn seconds_to_ticks(s string) string {
return (s.int() * 1000 / 30).str() return (s.int() * 1000 / 30).str()

View file

@ -1,5 +1,53 @@
module main module main
fn main() { import config
println() import cli
import os
fn generate_command() cli.Command {
return cli.Command{
name: 'convert'
usage: 'convert <from.toml> <to.cfg>'
description: 'Convert a ManageTTD TOML configuration file to an OpenTTD configuration file.'
required_args: 2
execute: fn (cmd cli.Command) ! {
from := cmd.args[0]
to := cmd.args[1]
@type := match from {
'openttd.toml' {
config.ConfigType.openttd
}
'private.toml' {
config.ConfigType.private
}
'secrets.toml' {
config.ConfigType.secrets
}
else {
return error('Unknown configuration file type, cannot convert.
Accepted file types are openttd.toml, private.toml and secrets.toml.')
}
}
managettd_config := config.managettd_config_from_file(from, @type)!
openttd_config_string := managettd_config.to_openttd_config()!.str()
os.write_file(to, openttd_config_string)!
println('Successfully converted ${from} to ${to}.')
}
}
}
fn main() {
mut command := cli.Command{
name: 'managettd'
description: 'OpenTTD server management software.'
version: '0.0.1'
commands: [
generate_command(),
]
}
command.setup()
command.parse(os.args)
} }