Update game to use TOML format for persistent data

This commit is contained in:
kinther 2026-01-23 09:27:09 -08:00
parent 18c92e2357
commit 2dcf2d7311
209 changed files with 12983 additions and 1982 deletions

View file

@ -394,10 +394,12 @@ configure_file(
# ========== Source-filer ==========
file(GLOB SRC_FILES src/*.c)
list(APPEND SRC_FILES third_party/tomlc99/toml.c)
# ========== Bygg kjørbar ==========
add_executable(circle ${SRC_FILES})
target_link_libraries(circle ${EXTRA_LIBS})
target_include_directories(circle PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tomlc99)
add_subdirectory(src/util)

View file

@ -64,7 +64,10 @@ Changes in v1.1.0-alpha:
* Migration away from OLC with new command "mcreate" and for builders to modify NPC's
* Fixed issue with msave not saving items in containers on NPC's
Features that would have been implemented in the next few releases:
Changes in v1.2.0-alpha:
* Replaced ASCII files in favor of TOML for ease of reading
Features that will be implemented in the next few releases:
* Height and weight normalized to species
* Stables allow for purchasing of mounts
@ -110,7 +113,6 @@ Features that would have been implemented in the next few releases:
...and down the road:
* Replace ASCII files in favor of SQL database on the backend
* Replace DG Scripts with a Python abstraction layer for modern scripting support
* Replace Oasis OLC with more modern interface for easing builder duties
* Discord server integration for ticketing and community

26
THIRD-PARTY-LICENSES.md Normal file
View file

@ -0,0 +1,26 @@
# Third-Party Licenses
## tomlc99 (TOML C library)
Copyright (c) CK Tan
https://github.com/cktan/tomlc99
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

445
doc/TOML_SCHEMA.md Normal file
View file

@ -0,0 +1,445 @@
# TOML Schema Proposal (Draft)
This is a draft schema for the planned TOML cutover of gameplay data only.
It mirrors all fields currently written by the ASCII formats. Values should
be written in full (including defaults) to preserve fidelity and avoid
behavior changes.
All filenames change to `.toml`. Index files become TOML too.
## Conventions
- Strings mirror existing text fields; preserve current escaping rules for
embedded newlines where applicable.
- Flags and bitvectors are stored as integer arrays unless otherwise noted.
- VNUM and RNUM are stored as integers.
- Timestamps are Unix epoch seconds.
## Accounts
Path: `lib/acctfiles/<A-E|F-J|K-O|P-T|U-Z|ZZZ>/<name>.toml`
```toml
name = "AccountName"
password = "hashed"
email = "user@example.com" # optional
current_pc = "CharName" # optional
pcs = ["CharOne", "CharTwo"]
```
## Player Index
Path: `lib/plrfiles/index.toml` (and `index.mini.toml` if mini mode persists)
```toml
[[player]]
id = 12345
name = "charname"
level = 10
flags = 0
last = 1700000000
```
## Player File
Path: `lib/plrfiles/<A-E|F-J|K-O|P-T|U-Z|ZZZ>/<name>.toml`
```toml
name = "CharName"
short_desc = "short desc" # optional
password = "hashed"
account = "AccountName" # optional
description = "long desc" # optional
background = "long background" # optional
poofin = "text" # optional
poofout = "text" # optional
sex = 0
class = 0
species = 0
level = 1
id = 12345
birth = 1700000000
age = 18
age_year = 205
played = 1234
logon = 1700000000
last_motd = 0
last_news = 0
reroll_used = 0
reroll_expires = 0
reroll_old_abils = [0, 0, 0, 0, 0, 0] # str int wis dex con cha
host = "example.net" # optional
height = 180
weight = 180
act_flags = [0, 0, 0, 0]
aff_flags = [0, 0, 0, 0]
pref_flags = [0, 0, 0, 0]
saving_throws = [0, 0, 0, 0, 0] # thr1..thr5
wimp = 0
freeze = 0
invis = 0
load_room = 0
bad_passwords = 0
conditions = { hunger = 0, thirst = 0, drunk = 0 }
hmv = { hit = 0, max_hit = 0, mana = 0, max_mana = 0, stamina = 0, max_stamina = 0 }
abilities = { str = 0, int = 0, wis = 0, dex = 0, con = 0, cha = 0 }
ac = 0
coins = 0
bank_coins = 0
exp = 0
olc_zone = 0
page_length = 0
screen_width = 0
quest_points = 0
quest_counter = 0
current_quest = 0
completed_quests = [101, 102]
triggers = [2001, 2002]
skill_gain_next = [0, 0, 0] # length MAX_SKILLS; index 1..MAX_SKILLS
[[skill]]
id = 1
level = 50
[[affect]]
spell = 0
duration = 0
modifier = 0
location = 0
bitvector = [0, 0, 0, 0]
[[alias]]
alias = "look"
replacement = "l"
type = 0
[[var]]
name = "quest_state"
context = 0
value = "value"
```
## Player Objects (Crash/Forced/Logout/etc.)
Path: `lib/plrobjs/<A-E|F-J|K-O|P-T|U-Z|ZZZ>/<name>.toml`
```toml
[header]
save_code = 0
timed = 0
net_cost = 0
coins = 0
account = 0
item_count = 0
[[object]]
vnum = 1234
locate = 0
nest = 0
values = [0, 0, 0, 0, 0, 0] # NUM_OBJ_VAL_POSITIONS
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
name = "obj name" # optional
short = "short desc" # optional
description = "long desc" # optional
main_description = "extra desc" # optional
type = 0
weight = 0
cost = 0
```
## Player Vars (standalone file)
Path: `lib/plrvars/<A-E|F-J|K-O|P-T|U-Z|ZZZ>/<name>.toml`
```toml
[[var]]
name = "varname"
context = 0
value = "value"
```
## Houses (objects only)
Path: `lib/house/<vnum>.toml`
```toml
[[object]]
vnum = 1234
locate = 0
nest = 0
values = [0, 0, 0, 0, 0, 0]
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
name = "obj name"
short = "short desc"
description = "long desc"
main_description = "extra desc"
type = 0
weight = 0
cost = 0
```
## Room Save
Path: `lib/world/rsv/<zone>.toml`
```toml
[[room]]
vnum = 1000
saved_at = 1700000000
[[room.object]]
vnum = 1234
timer = 0
weight = 0
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [0, 0, 0, 0, 0, 0]
contents = [] # recursive list of objects with same shape
[[room.mob]]
vnum = 2000
[[room.mob.equipment]]
wear_pos = 5
vnum = 1234
contents = [] # recursive list of objects by vnum only
[[room.mob.inventory]]
vnum = 1234
contents = []
```
## World Index Files
Paths:
- `lib/world/wld/index.toml`
- `lib/world/mob/index.toml`
- `lib/world/obj/index.toml`
- `lib/world/zon/index.toml`
- `lib/world/shp/index.toml`
- `lib/world/trg/index.toml`
- `lib/world/qst/index.toml`
```toml
files = ["0.toml", "1.toml"]
```
## Rooms
Path: `lib/world/wld/<zone>.toml`
```toml
[[room]]
vnum = 1000
name = "Room name"
description = "Room description"
flags = [0, 0, 0, 0]
sector = 0
[[room.exit]]
dir = 0
description = "exit desc"
keyword = "door"
exit_info = 0
key = 0
to_room = 1001
[[room.extra_desc]]
keyword = "sign"
description = "text"
[[room.forage]]
obj_vnum = 1234
dc = 10
room.triggers = [3000, 3001]
```
## Mobiles
Path: `lib/world/mob/<zone>.toml`
```toml
[[mob]]
vnum = 2000
name = "mob name"
keywords = "keywords"
short = "short"
long = "long"
description = "desc"
background = "background" # optional
flags = [0, 0, 0, 0]
aff_flags = [0, 0, 0, 0]
alignment = 0
mob_type = "simple" # "simple" or "enhanced"
[mob.simple]
level = 1
hit_dice = 1
mana_dice = 1
stamina_dice = 1
pos = 0
default_pos = 0
sex = 0
[mob.enhanced]
pos = 0
default_pos = 0
sex = 0
abilities = { str = 11, dex = 11, con = 11, int = 11, wis = 11, cha = 11 }
class = 0
species = 0
age = 0
saving_throws = { str = 0, dex = 0, con = 0, int = 0, wis = 0, cha = 0 }
skills = [{ id = 1, level = 50 }]
attack_type = 0
[[mob.loadout]]
wear_pos = 0
vnum = 1234
quantity = 1
[[mob.skin_yield]]
obj_vnum = 1234
dc = 10
mob.triggers = [3000, 3001]
```
## Objects
Path: `lib/world/obj/<zone>.toml`
```toml
[[object]]
vnum = 3000
name = "obj name"
short = "short"
description = "desc"
main_description = "long"
type = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
affect_flags = [0, 0, 0, 0]
values = [0, 0, 0, 0]
weight = 0
cost = 0
level = 0
timer = 0
[[object.extra_desc]]
keyword = "inscription"
description = "text"
[[object.affect]]
location = 0
modifier = 0
object.triggers = [3000, 3001]
```
## Zones
Path: `lib/world/zon/<zone>.toml`
```toml
[[zone]]
vnum = 1
builders = "None."
name = "Zone name"
bot = 100
top = 199
lifespan = 30
reset_mode = 2
flags = [0, 0, 0, 0]
min_level = -1
max_level = -1
[[zone.command]]
command = "M"
if_flag = 0
arg1 = 0
arg2 = 0
arg3 = 0
sarg1 = "" # for V command
sarg2 = "" # for V command
line = 0
```
## Shops
Path: `lib/world/shp/<zone>.toml`
```toml
[[shop]]
vnum = 4000
products = [3000, 3001]
buy_profit = 1.0
sell_profit = 1.0
trade_with = 0
broke_temper = 0
bitvector = 0
keeper = 2000
rooms = [1000]
open1 = 0
close1 = 28
open2 = 0
close2 = 0
bank = 0
sort = 0
[[shop.buy_type]]
type = 0
keyword = "" # optional
[shop.messages]
no_such_item1 = ""
no_such_item2 = ""
do_not_buy = ""
missing_cash1 = ""
missing_cash2 = ""
message_buy = ""
message_sell = ""
```
## Triggers
Path: `lib/world/trg/<zone>.toml`
```toml
[[trigger]]
vnum = 5000
name = "trigger name"
attach_type = 0
flags = 0
narg = 0
arglist = ""
commands = ["say hello", "wait 2", "say bye"]
```
## Quests
Path: `lib/world/qst/<zone>.toml`
```toml
[[quest]]
vnum = 6000
name = "Quest name"
description = "desc"
info = "info"
done = "done"
quit = "quit"
type = 0
quest_master = 2000
flags = 0
target = 0
prev_quest = 0
next_quest = 0
prereq = 0
values = [0, 0, 0, 0, 0, 0, 0]
rewards = { coins = 0, exp = 0, obj_vnum = 0 }
```

7
lib/plrfiles/index.toml Normal file
View file

@ -0,0 +1,7 @@
[[player]]
id = 1
name = "kinther"
level = 5
flags = 0
last = 1769189131

1
lib/world/mob/0.toml Normal file
View file

@ -0,0 +1 @@
mob = []

446
lib/world/mob/1.toml Normal file
View file

@ -0,0 +1,446 @@
[[mob]]
vnum = 100
name = "John"
keywords = "soldier tall burly human guard"
short = "the tall, burly human soldier"
long = "A tall, burly human soldier stands here at the gate.\n"
description = " This man stands slightly taller than the average human, but not by much. He\nhas a thick, haggard looking brown beard that is flecked with dust and sand. \nHis eyes have a bluish-tint to them with a small amount of green. One might\ncall his stature bulky, as he has quite a bit of muscle.\n"
flags = [6218, 0, 0, 0]
aff_flags = [0, 0, 0, 0]
alignment = 0
mob_type = "enhanced"
[mob.simple]
level = 1
hit_dice = 3
mana_dice = 20
stamina_dice = 40
pos = 8
default_pos = 8
sex = 1
[mob.enhanced]
class = 3
species = 0
[mob.enhanced.abilities]
str = 16
dex = 11
con = 11
int = 11
wis = 11
cha = 11
[mob.enhanced.saving_throws]
str = 0
dex = 0
con = 0
int = 0
wis = 0
cha = 0
[[mob.enhanced.skills]]
id = 132
level = 5
[[mob.enhanced.skills]]
id = 134
level = 5
[[mob.enhanced.skills]]
id = 137
level = 5
[[mob.enhanced.skills]]
id = 141
level = 5
[[mob.enhanced.skills]]
id = 142
level = 5
[[mob.enhanced.skills]]
id = 143
level = 5
[[mob.enhanced.skills]]
id = 144
level = 5
[[mob.enhanced.skills]]
id = 145
level = 5
[[mob.enhanced.skills]]
id = 146
level = 5
[[mob.enhanced.skills]]
id = 147
level = 5
[[mob.loadout]]
wear_pos = 3
vnum = 118
quantity = 1
[[mob.loadout]]
wear_pos = 5
vnum = 131
quantity = 1
[[mob.loadout]]
wear_pos = 6
vnum = 110
quantity = 1
[[mob.loadout]]
wear_pos = 7
vnum = 108
quantity = 1
[[mob.loadout]]
wear_pos = 8
vnum = 115
quantity = 1
[[mob.loadout]]
wear_pos = 9
vnum = 124
quantity = 1
[[mob.loadout]]
wear_pos = 10
vnum = 107
quantity = 1
[[mob.loadout]]
wear_pos = 11
vnum = 111
quantity = 1
[[mob.loadout]]
wear_pos = 15
vnum = 117
quantity = 1
[[mob.loadout]]
wear_pos = 16
vnum = 117
quantity = 1
[[mob.loadout]]
wear_pos = 17
vnum = 127
quantity = 1
[[mob]]
vnum = 101
name = "Sally"
keywords = "slim lanky human soldier guard"
short = "the slim, lanky human soldier"
long = "A slim, lanky human soldier stands here eyeing passerbys.\n"
description = " This woman looks rather thin, with her darkly tanned skin hugging her frame\ntightly. What muscle she does have is accentuated, though there is not much. \nHer arms and legs are lanky, seeming to be longer than normal. A ponytail of\ndark hair has been pulled back behind her head, intensifying the sharpness of\nher nose.\n"
flags = [6218, 0, 0, 0]
aff_flags = [0, 0, 0, 0]
alignment = 0
mob_type = "enhanced"
[mob.simple]
level = 1
hit_dice = 3
mana_dice = 20
stamina_dice = 40
pos = 8
default_pos = 8
sex = 2
[mob.enhanced]
class = 3
species = 0
[mob.enhanced.abilities]
str = 11
dex = 11
con = 11
int = 11
wis = 11
cha = 11
[mob.enhanced.saving_throws]
str = 0
dex = 0
con = 0
int = 0
wis = 0
cha = 0
[[mob.enhanced.skills]]
id = 132
level = 5
[[mob.enhanced.skills]]
id = 134
level = 5
[[mob.enhanced.skills]]
id = 137
level = 5
[[mob.enhanced.skills]]
id = 140
level = 5
[[mob.enhanced.skills]]
id = 141
level = 5
[[mob.enhanced.skills]]
id = 142
level = 5
[[mob.enhanced.skills]]
id = 143
level = 5
[[mob.enhanced.skills]]
id = 144
level = 5
[[mob.enhanced.skills]]
id = 145
level = 5
[[mob.enhanced.skills]]
id = 146
level = 5
[[mob.enhanced.skills]]
id = 152
level = 5
[[mob.enhanced.skills]]
id = 156
level = 5
[[mob.enhanced.skills]]
id = 163
level = 5
[[mob.loadout]]
wear_pos = 3
vnum = 118
quantity = 1
[[mob.loadout]]
wear_pos = 5
vnum = 131
quantity = 1
[[mob.loadout]]
wear_pos = 6
vnum = 110
quantity = 1
[[mob.loadout]]
wear_pos = 7
vnum = 108
quantity = 1
[[mob.loadout]]
wear_pos = 8
vnum = 115
quantity = 1
[[mob.loadout]]
wear_pos = 9
vnum = 124
quantity = 1
[[mob.loadout]]
wear_pos = 10
vnum = 107
quantity = 1
[[mob.loadout]]
wear_pos = 11
vnum = 111
quantity = 1
[[mob.loadout]]
wear_pos = 15
vnum = 117
quantity = 1
[[mob.loadout]]
wear_pos = 16
vnum = 117
quantity = 1
[[mob.loadout]]
wear_pos = 17
vnum = 127
quantity = 1
[[mob]]
vnum = 102
name = "Baldy"
keywords = "barkeep stocky bald"
short = "a stocky, bald barkeep"
long = "A stocky, bald barkeep stands behind the bar here.\n"
description = " This man is short and stocky, with a cleanly shaven head. Pattern baldness\nhas taken hold, yet he has a thick and wiry beard that covers most of his face.\nPale blue eyes look bloodshot, and bluish-purple bags hang under them. His\nhands are marred with minor cuts and scars from years of working in service to\nothers.\n"
flags = [10, 0, 0, 0]
aff_flags = [0, 0, 0, 0]
alignment = 0
mob_type = "enhanced"
[mob.simple]
level = 1
hit_dice = 3
mana_dice = 12
stamina_dice = 60
pos = 8
default_pos = 8
sex = 1
[mob.enhanced]
[mob.enhanced.abilities]
str = 11
dex = 11
con = 11
int = 11
wis = 11
cha = 11
[mob.enhanced.saving_throws]
str = 0
dex = 0
con = 0
int = 0
wis = 0
cha = 0
[[mob.loadout]]
wear_pos = 14
vnum = 113
quantity = 1
[[mob.loadout]]
wear_pos = 9
vnum = 112
quantity = 1
[[mob]]
vnum = 103
name = "Lanky"
keywords = "woman lanky scarred"
short = "the lanky, scarred woman"
long = "The lanky, scarred woman is leaning against a wall here.\n"
description = " This human woman is of average height and has a very lanky frame. Her skin\nhugs her body tightly and there is little fat to be seen, possibly due to\ndehydration. Tanned dark from the harsh rays of the sun, her upper torso is\ncovered in scars from a lifetime of labor. Unkempt brown hair covers her head,\ndescending to just above her shoulders. Her eyes are a light blue color and\nappear slightly bloodshot.\n"
flags = [10, 0, 0, 0]
aff_flags = [0, 0, 0, 0]
alignment = 0
mob_type = "enhanced"
[mob.simple]
level = 1
hit_dice = 3
mana_dice = 8
stamina_dice = 60
pos = 8
default_pos = 8
sex = 2
[mob.enhanced]
[mob.enhanced.abilities]
str = 11
dex = 11
con = 11
int = 11
wis = 11
cha = 11
[mob.enhanced.saving_throws]
str = 0
dex = 0
con = 0
int = 0
wis = 0
cha = 0
[[mob.enhanced.skills]]
id = 131
level = 5
[[mob.enhanced.skills]]
id = 133
level = 5
[[mob.enhanced.skills]]
id = 135
level = 5
[[mob.enhanced.skills]]
id = 138
level = 5
[[mob.enhanced.skills]]
id = 139
level = 5
[[mob.enhanced.skills]]
id = 140
level = 5
[[mob.enhanced.skills]]
id = 142
level = 5
[[mob.enhanced.skills]]
id = 143
level = 5
[[mob.enhanced.skills]]
id = 144
level = 5
[[mob.enhanced.skills]]
id = 147
level = 5
[[mob]]
vnum = 104
name = "Rat"
keywords = "rat small furry"
short = "a small, furry rat"
long = "Keeping low to the ground, a small, furry rat wanders around here.\n"
description = " This small rat is covered in thick fur. The fur itself appears matted and\nhas grime coating it. Two beady black eyes look around, constantly shifting. \nIts tail is four, perhaps five inches long and grey in color. Both hindlings\nappear thick and ready to propel the animal if it feels threatened.\n"
background = "\n\n\n\n\n\n\n\n\n\n\n\nIt's a rat.\n"
flags = [8, 0, 0, 0]
aff_flags = [0, 0, 0, 0]
alignment = 0
mob_type = "enhanced"
[mob.simple]
level = 1
hit_dice = 0
mana_dice = 0
stamina_dice = 10
pos = 8
default_pos = 8
sex = 2
[mob.enhanced]
species = 25
age = 42
attack_type = 4
[mob.enhanced.abilities]
str = 3
dex = 7
con = 8
int = 3
wis = 8
cha = 3
[mob.enhanced.saving_throws]
str = 0
dex = 0
con = 0
int = 0
wis = 0
cha = 0
[[mob]]
vnum = 105
name = "Kank"
keywords = "kank sandy brown"
short = "a sandy brown kank"
long = "A sandy brown kank is here, clacking its pincers.\n"
description = "It looks unfinished.\n"
background = "\n\n\n\nNo background has been recorded.\n"
flags = [1048584, 0, 0, 0]
aff_flags = [0, 0, 0, 0]
alignment = 0
mob_type = "enhanced"
[mob.simple]
level = 1
hit_dice = 0
mana_dice = 0
stamina_dice = 10
pos = 8
default_pos = 8
sex = 0
[mob.enhanced]
species = 21
attack_type = 4
[mob.enhanced.abilities]
str = 18
dex = 5
con = 18
int = 3
wis = 7
cha = 3
[mob.enhanced.saving_throws]
str = 0
dex = 0
con = 0
int = 0
wis = 0
cha = 0

View file

@ -0,0 +1,2 @@
files = [
]

4
lib/world/mob/index.toml Normal file
View file

@ -0,0 +1,4 @@
files = [
"0.toml",
"1.toml"
]

16
lib/world/obj/0.toml Normal file
View file

@ -0,0 +1,16 @@
[[object]]
vnum = 1
name = "board immortal"
short = "the immortal board"
description = "The immortal bulletin board is here."
main_description = "Made specifically for immortals to post on.\n"
type = 13
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
affect_flags = [0, 0, 0, 0]
values = [0, 0, 0, 0, 0, 0, 0, 0]
weight = 0
cost = 0
level = 0
timer = 0

1104
lib/world/obj/1.toml Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
files = [
]

4
lib/world/obj/index.toml Normal file
View file

@ -0,0 +1,4 @@
files = [
"0.toml",
"1.toml"
]

1
lib/world/qst/0.toml Normal file
View file

@ -0,0 +1 @@
quest = []

1
lib/world/qst/1.toml Normal file
View file

@ -0,0 +1 @@
quest = []

View file

@ -0,0 +1,2 @@
files = [
]

4
lib/world/qst/index.toml Normal file
View file

@ -0,0 +1,4 @@
files = [
"0.toml",
"1.toml"
]

15
lib/world/rsv/0.toml Normal file
View file

@ -0,0 +1,15 @@
[[room]]
vnum = 1
saved_at = 1759515981
[[room.object]]
vnum = 1
timer = 0
weight = 0
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [0, 0, 0, 0, 0, 0, 0, 0]
contents = []

287
lib/world/rsv/1.toml Normal file
View file

@ -0,0 +1,287 @@
[[room]]
vnum = 100
saved_at = 1759514843
[[room.mob]]
vnum = 100
[[room.mob.equipment]]
wear_pos = 3
vnum = 118
contents = []
[[room.mob.equipment]]
wear_pos = 5
vnum = 131
contents = []
[[room.mob.equipment]]
wear_pos = 6
vnum = 110
contents = []
[[room.mob.equipment]]
wear_pos = 7
vnum = 108
contents = []
[[room.mob.equipment]]
wear_pos = 8
vnum = 115
contents = []
[[room.mob.equipment]]
wear_pos = 9
vnum = 124
contents = []
[[room.mob.equipment]]
wear_pos = 10
vnum = 107
contents = []
[[room.mob.equipment]]
wear_pos = 11
vnum = 111
contents = []
[[room.mob.equipment]]
wear_pos = 15
vnum = 117
contents = []
[[room.mob.equipment]]
wear_pos = 16
vnum = 117
contents = []
[[room.mob.equipment]]
wear_pos = 17
vnum = 127
contents = []
[[room.mob]]
vnum = 101
[[room.mob.equipment]]
wear_pos = 3
vnum = 118
contents = []
[[room.mob.equipment]]
wear_pos = 5
vnum = 131
contents = []
[[room.mob.equipment]]
wear_pos = 6
vnum = 110
contents = []
[[room.mob.equipment]]
wear_pos = 7
vnum = 108
contents = []
[[room.mob.equipment]]
wear_pos = 8
vnum = 115
contents = []
[[room.mob.equipment]]
wear_pos = 9
vnum = 124
contents = []
[[room.mob.equipment]]
wear_pos = 10
vnum = 107
contents = []
[[room.mob.equipment]]
wear_pos = 11
vnum = 111
contents = []
[[room.mob.equipment]]
wear_pos = 15
vnum = 117
contents = []
[[room.mob.equipment]]
wear_pos = 16
vnum = 117
contents = []
[[room.mob.equipment]]
wear_pos = 17
vnum = 127
contents = []
[[room]]
vnum = 200
saved_at = 1759595106
[[room.object]]
vnum = 143
timer = 0
weight = 10
cost = 100
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [1, 0, 0, 0, 0, 0, 0, 0]
contents = []
[[room]]
vnum = 136
saved_at = 1759603517
[[room.object]]
vnum = 147
timer = 0
weight = 100
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [0, 0, 0, 0, 0, 0, 0, 0]
contents = []
[[room]]
vnum = 134
saved_at = 1760390381
[[room.object]]
vnum = 134
timer = 0
weight = 100
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [2, 0, 0, 0, 0, 0, 0, 0]
contents = []
[[room.object]]
vnum = 133
timer = 0
weight = 100
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [6, 0, 1, 0, 0, 0, 0, 0]
contents = []
[[room.object]]
vnum = 132
timer = 0
weight = 200
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [8, 0, 0, 0, 0, 0, 0, 0]
contents = []
[[room.object]]
vnum = 150
timer = 0
weight = 0
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [0, 0, 0, 0, 0, 0, 0, 0]
contents = []
[[room.mob]]
vnum = 102
[[room.mob.equipment]]
wear_pos = 9
vnum = 112
contents = []
[[room.mob.equipment]]
wear_pos = 14
vnum = 113
contents = []
[[room.mob.inventory]]
vnum = 138
contents = []
[[room.mob.inventory]]
vnum = 137
contents = []
[[room.mob.inventory]]
vnum = 136
contents = []
[[room.mob.inventory]]
vnum = 135
contents = []
[[room.mob.inventory]]
vnum = 139
contents = []
[[room.mob.inventory]]
vnum = 140
contents = []
[[room.mob.inventory]]
vnum = 141
contents = []
[[room.mob.inventory]]
vnum = 142
contents = []
[[room.mob]]
vnum = 103
[[room]]
vnum = 131
saved_at = 1767296856
[[room.object]]
vnum = 144
timer = 0
weight = 20
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [100, 100, 0, 0, 0, 0, 0, 0]
contents = []
[[room.object]]
vnum = 145
timer = 0
weight = 40
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [4, 0, 2, 0, 0, 0, 0, 0]
contents = []
[[room.object]]
vnum = 146
timer = 0
weight = 80
cost = 0
cost_per_day = 0
extra_flags = [0, 0, 0, 0]
wear_flags = [0, 0, 0, 0]
values = [6, 0, 2, 0, 0, 0, 0, 0]
contents = []
[[room]]
vnum = 101
saved_at = 1767296996

1
lib/world/shp/0.toml Normal file
View file

@ -0,0 +1 @@
shop = []

54
lib/world/shp/1.toml Normal file
View file

@ -0,0 +1,54 @@
[[shop]]
vnum = 100
products = [135, 136, 137, 138, 139, 140, 141, 142]
buy_profit = 1.00
sell_profit = 1.00
broke_temper = 0
bitvector = 4
keeper = 102
trade_with = 0
rooms = [134]
open1 = 0
close1 = 28
open2 = 0
close2 = 0
bank = 0
sort = 0
[shop.messages]
no_such_item1 = "%s We're fresh out of that."
no_such_item2 = "%s Trying to sell something you don't have?"
do_not_buy = "%s Not interested. Try someone else."
missing_cash1 = "%s I can't afford that!"
missing_cash2 = "%s Come back when you have some coin."
message_buy = "%s That'll be %d coins."
message_sell = "%s I'll give you %d coins for that."
[[shop]]
vnum = 101
products = [138]
buy_profit = 1.00
sell_profit = 1.00
broke_temper = 0
bitvector = 0
keeper = 103
trade_with = 0
rooms = []
open1 = 0
close1 = 28
open2 = 0
close2 = 0
bank = 0
sort = 0
[shop.messages]
no_such_item1 = "%s Sorry, I don't stock that item."
no_such_item2 = "%s You don't seem to have that."
do_not_buy = "%s I don't trade in such items."
missing_cash1 = "%s I can't afford that!"
missing_cash2 = "%s You are too poor!"
message_buy = "%s That'll be %d coins, thanks."
message_sell = "%s I'll give you %d coins for that."

View file

@ -0,0 +1,2 @@
files = [
]

4
lib/world/shp/index.toml Normal file
View file

@ -0,0 +1,4 @@
files = [
"0.toml",
"1.toml"
]

11
lib/world/trg/0.toml Normal file
View file

@ -0,0 +1,11 @@
[[trigger]]
vnum = 1
name = "Test"
attach_type = 0
flags = 65536
narg = 1
arglist = ""
commands = [
"* No Script",
]

1
lib/world/trg/1.toml Normal file
View file

@ -0,0 +1 @@
trigger = []

1
lib/world/trg/2.toml Normal file
View file

@ -0,0 +1 @@
trigger = []

View file

@ -0,0 +1,2 @@
files = [
]

5
lib/world/trg/index.toml Normal file
View file

@ -0,0 +1,5 @@
files = [
"0.toml",
"1.toml",
"2.toml"
]

7
lib/world/wld/0.toml Normal file
View file

@ -0,0 +1,7 @@
[[room]]
vnum = 1
name = "Limbo"
description = "Floating in the void, you lose all sense of time and space.\n"
flags = [0, 0, 0, 0]
sector = 0

2370
lib/world/wld/1.toml Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
files = [
]

4
lib/world/wld/index.toml Normal file
View file

@ -0,0 +1,4 @@
files = [
"0.toml",
"1.toml"
]

12
lib/world/zon/0.toml Normal file
View file

@ -0,0 +1,12 @@
[[zone]]
vnum = 0
builders = "Immortal Zone"
name = "Kinther"
bot = 1
top = 99
lifespan = 30
reset_mode = 2
flags = [0, 0, 0, 0]
min_level = -1
max_level = -1

12
lib/world/zon/1.toml Normal file
View file

@ -0,0 +1,12 @@
[[zone]]
vnum = 1
builders = "City of Caleran"
name = "Kinther"
bot = 100
top = 999
lifespan = 30
reset_mode = 2
flags = [0, 0, 0, 0]
min_level = -1
max_level = -1

View file

@ -0,0 +1,2 @@
files = [
]

4
lib/world/zon/index.toml Normal file
View file

@ -0,0 +1,4 @@
files = [
"0.toml",
"1.toml"
]

View file

@ -16,6 +16,8 @@ file(GLOB CIRCLE_SOURCES
)
add_executable(circle ${CIRCLE_SOURCES})
target_sources(circle PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tomlc99/toml.c)
target_include_directories(circle PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tomlc99)
if(MSVC)
target_link_libraries(circle wsock32.lib)
@ -23,4 +25,4 @@ if(MSVC)
set_target_properties(circle PROPERTIES
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/.."
)
endif()
endif()

View file

@ -17,11 +17,11 @@ PROFILE =
BINDIR = ../bin
CFLAGS = -g -O2 $(MYFLAGS) $(PROFILE)
CFLAGS = -g -O2 $(MYFLAGS) $(PROFILE) -I../third_party/tomlc99
LIBS = -lcrypt
SRCFILES := $(shell ls *.c | sort)
SRCFILES := $(shell ls *.c | sort) ../third_party/tomlc99/toml.c
OBJFILES := $(patsubst %.c,%.o,$(SRCFILES))
default: all
@ -47,13 +47,14 @@ $%.o: %.c
clean:
rm -f *.o depend
rm -f ../third_party/tomlc99/toml.o
rm -f ./tests/*.o depend
# Dependencies for the object files (automagically generated with
# gcc -MM)
depend:
$(CC) -MM *.c > depend
$(CC) $(CFLAGS) -MM *.c > depend
-include depend

View file

@ -16,11 +16,11 @@ PROFILE =
BINDIR = ../bin
CFLAGS = @CFLAGS@ $(MYFLAGS) $(PROFILE)
CFLAGS = @CFLAGS@ $(MYFLAGS) $(PROFILE) -I../third_party/tomlc99
LIBS = @LIBS@ @CRYPTLIB@ @NETLIB@
SRCFILES := $(shell ls *.c | sort)
SRCFILES := $(shell ls *.c | sort) ../third_party/tomlc99/toml.c
OBJFILES := $(patsubst %.c,%.o,$(SRCFILES))
default: all
@ -46,6 +46,7 @@ $%.o: %.c
clean:
rm -f *.o depend
rm -f ../third_party/tomlc99/toml.o
rm -f ./tests/*.o depend
# Dependencies for the object files (automagically generated with

View file

@ -12,6 +12,8 @@
#include "utils.h"
#include "db.h"
#include "accounts.h"
#include "toml.h"
#include "toml_utils.h"
static void set_account_name(struct account_data *account, const char *name)
{
@ -28,6 +30,31 @@ static void set_account_name(struct account_data *account, const char *name)
account->name = strdup(tmp);
}
static char *toml_dup_string(toml_table_t *tab, const char *key)
{
toml_datum_t d = toml_string_in(tab, key);
if (!d.ok)
return NULL;
return d.u.s;
}
static void toml_set_account_pc_name(struct account_data *account, const char *value)
{
char tmp[MAX_INPUT_LENGTH];
if (!value || !*value)
return;
strlcpy(tmp, value, sizeof(tmp));
CAP(tmp);
if (account->pc_name)
free(account->pc_name);
account->pc_name = strdup(tmp);
}
int account_has_pc(const struct account_data *account, const char *pc_name)
{
int i;
@ -77,9 +104,11 @@ struct account_data *account_load(const char *name)
struct account_data *account;
FILE *fl;
char filename[PATH_MAX];
char line[MAX_INPUT_LENGTH + 1];
char tag[6];
int i;
char errbuf[256];
toml_table_t *tab = NULL;
toml_array_t *arr = NULL;
char *value = NULL;
int i, count;
if (!name || !*name)
return NULL;
@ -91,29 +120,55 @@ struct account_data *account_load(const char *name)
if (!fl)
return NULL;
tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
fclose(fl);
if (!tab) {
log("SYSERR: Couldn't parse account file %s: %s.", filename, errbuf);
return NULL;
}
account = account_create(NULL);
while (get_line(fl, line)) {
tag_argument(line, tag);
value = toml_dup_string(tab, "name");
if (value) {
set_account_name(account, value);
free(value);
}
if (!strcmp(tag, "Name"))
set_account_name(account, line);
else if (!strcmp(tag, "Pass"))
strlcpy(account->passwd, line, sizeof(account->passwd));
else if (!strcmp(tag, "Mail")) {
if (account->email)
free(account->email);
account->email = strdup(line);
} else if (!strcmp(tag, "Char"))
account_add_pc(account, line);
else if (!strcmp(tag, "Curr")) {
if (account->pc_name)
free(account->pc_name);
account->pc_name = strdup(line);
value = toml_dup_string(tab, "password");
if (value) {
strlcpy(account->passwd, value, sizeof(account->passwd));
free(value);
}
value = toml_dup_string(tab, "email");
if (value) {
if (account->email)
free(account->email);
account->email = value;
}
value = toml_dup_string(tab, "current_pc");
if (value) {
toml_set_account_pc_name(account, value);
free(value);
}
arr = toml_array_in(tab, "pcs");
if (arr) {
count = toml_array_nelem(arr);
for (i = 0; i < count; i++) {
toml_datum_t d = toml_string_at(arr, i);
if (!d.ok) {
log("SYSERR: Invalid account character entry %d in %s.", i, filename);
continue;
}
account_add_pc(account, d.u.s);
free(d.u.s);
}
}
fclose(fl);
toml_free(tab);
if (!account->name)
set_account_name(account, name);
@ -151,14 +206,33 @@ int account_save(const struct account_data *account)
return 0;
}
fprintf(fl, "Name: %s\n", account->name);
fprintf(fl, "Pass: %s\n", account->passwd);
fprintf(fl, "name = ");
toml_write_string(fl, account->name);
fprintf(fl, "\n");
fprintf(fl, "password = ");
toml_write_string(fl, account->passwd);
fprintf(fl, "\n");
if (account->email && *account->email)
fprintf(fl, "Mail: %s\n", account->email);
{
fprintf(fl, "email = ");
toml_write_string(fl, account->email);
fprintf(fl, "\n");
}
if (account->pc_name && *account->pc_name)
fprintf(fl, "Curr: %s\n", account->pc_name);
for (i = 0; i < account->pc_count; i++)
fprintf(fl, "Char: %s\n", account->pc_list[i]);
{
fprintf(fl, "current_pc = ");
toml_write_string(fl, account->pc_name);
fprintf(fl, "\n");
}
if (account->pc_count > 0) {
fprintf(fl, "pcs = [\n");
for (i = 0; i < account->pc_count; i++) {
fprintf(fl, " ");
toml_write_string(fl, account->pc_list[i]);
fprintf(fl, "%s\n", (i + 1 < account->pc_count) ? "," : "");
}
fprintf(fl, "]\n");
}
fclose(fl);
return 1;

1437
src/db.c

File diff suppressed because it is too large Load diff

View file

@ -54,11 +54,11 @@
#error "Unknown path components."
#endif
#define SUF_OBJS "objs"
#define SUF_OBJS "objs.toml"
#define SUF_TEXT "text"
#define SUF_MEM "mem"
#define SUF_PLR "plr"
#define SUF_ACCT "acc"
#define SUF_MEM "mem.toml"
#define SUF_PLR "plr.toml"
#define SUF_ACCT "acc.toml"
#if defined(CIRCLE_AMIGA)
#define EXE_FILE "/bin/circle" /* maybe use argv[0] but it's not reliable */
@ -77,8 +77,8 @@
#endif
/* names of various files and directories */
#define INDEX_FILE "index" /* index of world files */
#define MINDEX_FILE "index.mini" /* ... and for mini-mud-mode */
#define INDEX_FILE "index.toml" /* index of world files */
#define MINDEX_FILE "index.mini.toml" /* ... and for mini-mud-mode */
#define WLD_PREFIX LIB_WORLD"wld"SLASH /* room definitions */
#define MOB_PREFIX LIB_WORLD"mob"SLASH /* monster prototypes */
#define OBJ_PREFIX LIB_WORLD"obj"SLASH /* object prototypes */

View file

@ -113,6 +113,7 @@ ACMD(do_oasis_trigedit)
void script_save_to_disk(FILE *fp, void *item, int type)
{
struct trig_proto_list *t;
int first = 1;
if (type==MOB_TRIGGER)
t = ((struct char_data *)item)->proto_script;
@ -125,11 +126,18 @@ void script_save_to_disk(FILE *fp, void *item, int type)
return;
}
while (t)
{
fprintf(fp,"T %d\n", t->vnum);
if (!t)
return;
fprintf(fp, "triggers = [");
while (t) {
if (!first)
fputs(", ", fp);
fprintf(fp, "%d", t->vnum);
first = 0;
t = t->next;
}
fputs("]\n", fp);
}
static void trigedit_setup_new(struct descriptor_data *d)
@ -852,9 +860,9 @@ void trigedit_save(struct descriptor_data *d)
fclose(trig_file);
#ifdef CIRCLE_MAC
snprintf(buf, sizeof(buf), "%s:%d.trg", TRG_PREFIX, zone);
snprintf(buf, sizeof(buf), "%s:%d.toml", TRG_PREFIX, zone);
#else
snprintf(buf, sizeof(buf), "%s/%d.trg", TRG_PREFIX, zone);
snprintf(buf, sizeof(buf), "%s/%d.toml", TRG_PREFIX, zone);
#endif
remove(buf);

View file

@ -29,6 +29,8 @@
#include "genzon.h" /* for real_zone_by_thing */
#include "act.h"
#include "modify.h"
#include "toml.h"
#include "toml_utils.h"
#define PULSES_PER_MUD_HOUR (SECS_PER_MUD_HOUR*PASSES_PER_SEC)
@ -2826,11 +2828,11 @@ static struct cmdlist_element *find_done(struct cmdlist_element *cl)
void read_saved_vars(struct char_data *ch)
{
FILE *file;
long context;
char fn[127];
char input_line[1024], *temp, *p;
char varname[32];
char context_str[16];
char errbuf[256];
toml_table_t *tab = NULL;
toml_array_t *arr = NULL;
int i, count;
/* If getting to the menu from inside the game, the vars aren't removed. So
* let's not allocate them again. */
@ -2851,22 +2853,44 @@ void read_saved_vars(struct char_data *ch)
log("%s had no variable file", GET_NAME(ch));
return;
}
/* walk through each line in the file parsing variables */
do {
if (get_line(file, input_line)>0) {
p = temp = strdup(input_line);
temp = any_one_arg(temp, varname);
temp = any_one_arg(temp, context_str);
skip_spaces(&temp); /* temp now points to the rest of the line */
context = atol(context_str);
add_var(&(SCRIPT(ch)->global_vars), varname, temp, context);
free(p); /* plug memory hole */
}
} while( !feof(file) );
/* close the file and return */
tab = toml_parse_file(file, errbuf, sizeof(errbuf));
fclose(file);
if (!tab) {
log("SYSERR: Could not parse variable file %s: %s", fn, errbuf);
return;
}
arr = toml_array_in(tab, "var");
if (!arr) {
toml_free(tab);
return;
}
count = toml_array_nelem(arr);
for (i = 0; i < count; i++) {
toml_table_t *var_tab = toml_table_at(arr, i);
toml_datum_t name;
toml_datum_t value;
toml_datum_t context;
if (!var_tab)
continue;
name = toml_string_in(var_tab, "name");
value = toml_string_in(var_tab, "value");
context = toml_int_in(var_tab, "context");
if (!name.ok || !value.ok)
continue;
add_var(&(SCRIPT(ch)->global_vars), name.u.s, value.u.s,
context.ok ? (long)context.u.i : 0);
free(name.u.s);
free(value.u.s);
}
toml_free(tab);
}
/* save a characters variables out to disk */
@ -2901,7 +2925,12 @@ void save_char_vars(struct char_data *ch)
* future. */
while (vars) {
if (*vars->name != '-') /* don't save if it begins with - */
fprintf(file, "%s %ld %s\n", vars->name, vars->context, vars->value);
{
fprintf(file, "[[var]]\n");
toml_write_kv_string(file, "name", vars->name);
fprintf(file, "context = %ld\n", vars->context);
toml_write_kv_string(file, "value", vars->value);
}
vars = vars->next;
}

View file

@ -17,6 +17,7 @@
#include "genzon.h"
#include "dg_olc.h"
#include "spells.h"
#include "toml_utils.h"
/* local functions */
static void extract_mobile_all(mob_vnum vnum);
@ -312,10 +313,9 @@ int save_mobiles(zone_rnum rznum)
if (write_mobile_record(i, &mob_proto[rmob], mobfd) < 0)
log("SYSERR: GenOLC: Error writing mobile #%d.", i);
}
fputs("$\n", mobfd);
written = ftell(mobfd);
fclose(mobfd);
snprintf(usedfname, sizeof(usedfname), "%s%d.mob", MOB_PREFIX, vznum);
snprintf(usedfname, sizeof(usedfname), "%s%d.toml", MOB_PREFIX, vznum);
remove(usedfname);
rename(mobfname, usedfname);
@ -407,7 +407,6 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
char ldesc[MAX_STRING_LENGTH];
char ddesc[MAX_STRING_LENGTH];
char bdesc[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
int has_bdesc = 0;
ldesc[MAX_STRING_LENGTH - 1] = '\0';
@ -429,94 +428,71 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
} else
bdesc[0] = '\0';
int n;
if (has_bdesc) {
n = snprintf(buf, MAX_STRING_LENGTH,
"#%d\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"B\n"
"%s%c\n",
mvnum,
GET_NAME(mob), STRING_TERMINATOR,
GET_KEYWORDS(mob), STRING_TERMINATOR,
GET_SDESC(mob), STRING_TERMINATOR,
ldesc, STRING_TERMINATOR,
ddesc, STRING_TERMINATOR,
bdesc, STRING_TERMINATOR);
} else {
n = snprintf(buf, MAX_STRING_LENGTH,
"#%d\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n",
mvnum,
GET_NAME(mob), STRING_TERMINATOR,
GET_KEYWORDS(mob), STRING_TERMINATOR,
GET_SDESC(mob), STRING_TERMINATOR,
ldesc, STRING_TERMINATOR,
ddesc, STRING_TERMINATOR);
}
fprintf(fd, "[[mob]]\n");
fprintf(fd, "vnum = %d\n", mvnum);
toml_write_kv_string(fd, "name", GET_NAME(mob));
toml_write_kv_string(fd, "keywords", GET_KEYWORDS(mob));
toml_write_kv_string(fd, "short", GET_SDESC(mob));
toml_write_kv_string(fd, "long", ldesc);
toml_write_kv_string(fd, "description", ddesc);
if (has_bdesc)
toml_write_kv_string_opt(fd, "background", bdesc);
if (n >= MAX_STRING_LENGTH) {
mudlog(BRF, LVL_BUILDER, TRUE,
"SYSERR: Could not save mobile #%d due to size (%d > maximum of %d)",
mvnum, n, MAX_STRING_LENGTH);
return TRUE;
}
fprintf(fd, "%s", convert_from_tabs(buf));
/* --- FLAGS/AFFECT/ALIGN line --- */
fprintf(fd,
"%d %d %d %d %d %d %d %d %d E\n",
fprintf(fd, "flags = [%d, %d, %d, %d]\n",
MOB_FLAGS(mob)[0], MOB_FLAGS(mob)[1],
MOB_FLAGS(mob)[2], MOB_FLAGS(mob)[3],
MOB_FLAGS(mob)[2], MOB_FLAGS(mob)[3]);
fprintf(fd, "aff_flags = [%d, %d, %d, %d]\n",
AFF_FLAGS(mob)[0], AFF_FLAGS(mob)[1],
AFF_FLAGS(mob)[2], AFF_FLAGS(mob)[3],
GET_ALIGNMENT(mob));
AFF_FLAGS(mob)[2], AFF_FLAGS(mob)[3]);
fprintf(fd, "alignment = %d\n", GET_ALIGNMENT(mob));
toml_write_kv_string(fd, "mob_type", "enhanced");
/* --- Level, hitdice, mana, move --- */
fprintf(fd, "%d %dd%d+%d\n",
GET_LEVEL(mob),
GET_HIT(mob),
GET_MANA(mob),
GET_STAMINA(mob));
fprintf(fd, "\n[mob.simple]\n");
fprintf(fd, "level = %d\n", GET_LEVEL(mob));
fprintf(fd, "hit_dice = %d\n", GET_HIT(mob));
fprintf(fd, "mana_dice = %d\n", GET_MANA(mob));
fprintf(fd, "stamina_dice = %d\n", GET_STAMINA(mob));
fprintf(fd, "pos = %d\n", GET_POS(mob));
fprintf(fd, "default_pos = %d\n", GET_DEFAULT_POS(mob));
fprintf(fd, "sex = %d\n", GET_SEX(mob));
/* --- Position / default position / sex --- */
fprintf(fd, "%d %d %d\n",
GET_POS(mob),
GET_DEFAULT_POS(mob),
GET_SEX(mob));
fprintf(fd, "\n[mob.enhanced]\n");
fprintf(fd, "class = %d\n", GET_CLASS(mob));
fprintf(fd, "species = %d\n", GET_SPECIES(mob));
fprintf(fd, "age = %d\n", GET_ROLEPLAY_AGE(mob));
fprintf(fd, "attack_type = %d\n", mob->mob_specials.attack_type);
/* --- Enhanced (E-spec + Skills) --- */
if (write_mobile_espec(mvnum, mob, fd) < 0)
log("SYSERR: GenOLC: Error writing E-specs for mobile #%d.", mvnum);
fprintf(fd, "\n[mob.enhanced.abilities]\n");
fprintf(fd, "str = %d\n", GET_STR(mob));
fprintf(fd, "dex = %d\n", GET_DEX(mob));
fprintf(fd, "con = %d\n", GET_CON(mob));
fprintf(fd, "int = %d\n", GET_INT(mob));
fprintf(fd, "wis = %d\n", GET_WIS(mob));
fprintf(fd, "cha = %d\n", GET_CHA(mob));
fprintf(fd, "\n[mob.enhanced.saving_throws]\n");
fprintf(fd, "str = %d\n", GET_SAVE(mob, ABIL_STR));
fprintf(fd, "dex = %d\n", GET_SAVE(mob, ABIL_DEX));
fprintf(fd, "con = %d\n", GET_SAVE(mob, ABIL_CON));
fprintf(fd, "int = %d\n", GET_SAVE(mob, ABIL_INT));
fprintf(fd, "wis = %d\n", GET_SAVE(mob, ABIL_WIS));
fprintf(fd, "cha = %d\n", GET_SAVE(mob, ABIL_CHA));
/* Write NPC skills (if any set) */
for (int s = 0; s < MAX_SKILLS; s++) {
if (mob->mob_specials.skills[s] > 0)
fprintf(fd, "Skill %d %d\n", s, mob->mob_specials.skills[s]);
if (mob->mob_specials.skills[s] > 0) {
fprintf(fd, "\n[[mob.enhanced.skills]]\n");
fprintf(fd, "id = %d\n", s);
fprintf(fd, "level = %d\n", mob->mob_specials.skills[s]);
}
}
/* Write attack type (if set) */
if (mob->mob_specials.attack_type > 0)
fprintf(fd, "AtkT %d\n", mob->mob_specials.attack_type);
/* Single proper terminator */
fprintf(fd, "E\n");
/* --- Loadout lines --- */
/* --- Loadout entries --- */
for (struct mob_loadout *e = mob->proto_loadout; e; e = e->next) {
fprintf(fd, "L %d %d %d\n",
(int)e->wear_pos,
(int)e->vnum,
MAX(1, e->quantity));
fprintf(fd, "\n[[mob.loadout]]\n");
fprintf(fd, "wear_pos = %d\n", (int)e->wear_pos);
fprintf(fd, "vnum = %d\n", (int)e->vnum);
fprintf(fd, "quantity = %d\n", MAX(1, e->quantity));
}
/* --- DG Scripts --- */
@ -528,10 +504,11 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
struct skin_yield_entry *sy;
if (rmob != NOBODY && mob_index[rmob].skin_yields) {
fprintf(fd, "Y\n");
for (sy = mob_index[rmob].skin_yields; sy; sy = sy->next)
fprintf(fd, "%d %d\n", sy->obj_vnum, sy->dc);
fprintf(fd, "0 0\n");
for (sy = mob_index[rmob].skin_yields; sy; sy = sy->next) {
fprintf(fd, "\n[[mob.skin_yield]]\n");
fprintf(fd, "obj_vnum = %d\n", sy->obj_vnum);
fprintf(fd, "dc = %d\n", sy->dc);
}
}
}
@ -540,6 +517,7 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
log("SYSERR: GenOLC: Error writing MobProgs for mobile #%d.", mvnum);
#endif
fputc('\n', fd);
return TRUE;
}

View file

@ -19,6 +19,7 @@
#include "handler.h"
#include "interpreter.h"
#include "boards.h" /* for board_info */
#include "toml_utils.h"
/* local functions */
@ -178,10 +179,7 @@ obj_rnum index_object(struct obj_data *obj, obj_vnum ovnum, obj_rnum ornum)
int save_objects(zone_rnum zone_num)
{
char filename[128], buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
char ebuf1[MAX_STRING_LENGTH], ebuf2[MAX_STRING_LENGTH], ebuf3[MAX_STRING_LENGTH], ebuf4[MAX_STRING_LENGTH];
char wbuf1[MAX_STRING_LENGTH], wbuf2[MAX_STRING_LENGTH], wbuf3[MAX_STRING_LENGTH], wbuf4[MAX_STRING_LENGTH];
char pbuf1[MAX_STRING_LENGTH], pbuf2[MAX_STRING_LENGTH], pbuf3[MAX_STRING_LENGTH], pbuf4[MAX_STRING_LENGTH];
char filename[128], buf[MAX_STRING_LENGTH];
int counter, counter2, realcounter;
FILE *fp;
struct obj_data *obj;
@ -210,54 +208,33 @@ int save_objects(zone_rnum zone_num)
} else
*buf = '\0';
int n = snprintf(buf2, MAX_STRING_LENGTH,
"#%d\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n",
GET_OBJ_VNUM(obj),
(obj->name && *obj->name) ? obj->name : "undefined",
(obj->short_description && *obj->short_description) ? obj->short_description : "undefined",
(obj->description && *obj->description) ? obj->description : "undefined",
buf);
if(n >= MAX_STRING_LENGTH) {
mudlog(BRF,LVL_BUILDER,TRUE,
"SYSERR: Could not save object #%d due to size (%d > maximum of %d).",
GET_OBJ_VNUM(obj), n, MAX_STRING_LENGTH);
continue;
fprintf(fp, "[[object]]\n");
fprintf(fp, "vnum = %d\n", GET_OBJ_VNUM(obj));
toml_write_kv_string(fp, "name", (obj->name && *obj->name) ? obj->name : "undefined");
toml_write_kv_string(fp, "short", (obj->short_description && *obj->short_description) ? obj->short_description : "undefined");
toml_write_kv_string(fp, "description", (obj->description && *obj->description) ? obj->description : "undefined");
toml_write_kv_string(fp, "main_description", buf);
fprintf(fp, "type = %d\n", GET_OBJ_TYPE(obj));
fprintf(fp, "extra_flags = [%d, %d, %d, %d]\n",
GET_OBJ_EXTRA(obj)[0], GET_OBJ_EXTRA(obj)[1],
GET_OBJ_EXTRA(obj)[2], GET_OBJ_EXTRA(obj)[3]);
fprintf(fp, "wear_flags = [%d, %d, %d, %d]\n",
GET_OBJ_WEAR(obj)[0], GET_OBJ_WEAR(obj)[1],
GET_OBJ_WEAR(obj)[2], GET_OBJ_WEAR(obj)[3]);
fprintf(fp, "affect_flags = [%d, %d, %d, %d]\n",
GET_OBJ_AFFECT(obj)[0], GET_OBJ_AFFECT(obj)[1],
GET_OBJ_AFFECT(obj)[2], GET_OBJ_AFFECT(obj)[3]);
fprintf(fp, "values = [");
for (counter2 = 0; counter2 < NUM_OBJ_VAL_POSITIONS; counter2++) {
if (counter2)
fputs(", ", fp);
fprintf(fp, "%d", GET_OBJ_VAL(obj, counter2));
}
fprintf(fp, "%s", convert_from_tabs(buf2));
sprintascii(ebuf1, GET_OBJ_EXTRA(obj)[0]);
sprintascii(ebuf2, GET_OBJ_EXTRA(obj)[1]);
sprintascii(ebuf3, GET_OBJ_EXTRA(obj)[2]);
sprintascii(ebuf4, GET_OBJ_EXTRA(obj)[3]);
sprintascii(wbuf1, GET_OBJ_WEAR(obj)[0]);
sprintascii(wbuf2, GET_OBJ_WEAR(obj)[1]);
sprintascii(wbuf3, GET_OBJ_WEAR(obj)[2]);
sprintascii(wbuf4, GET_OBJ_WEAR(obj)[3]);
sprintascii(pbuf1, GET_OBJ_AFFECT(obj)[0]);
sprintascii(pbuf2, GET_OBJ_AFFECT(obj)[1]);
sprintascii(pbuf3, GET_OBJ_AFFECT(obj)[2]);
sprintascii(pbuf4, GET_OBJ_AFFECT(obj)[3]);
fprintf(fp, "%d %s %s %s %s %s %s %s %s %s %s %s %s\n"
"%d %d %d %d\n"
"%d %d %d %d %d\n",
GET_OBJ_TYPE(obj),
ebuf1, ebuf2, ebuf3, ebuf4,
wbuf1, wbuf2, wbuf3, wbuf4,
pbuf1, pbuf2, pbuf3, pbuf4,
GET_OBJ_VAL(obj, 0), GET_OBJ_VAL(obj, 1),
GET_OBJ_VAL(obj, 2), GET_OBJ_VAL(obj, 3),
GET_OBJ_WEIGHT(obj), GET_OBJ_COST(obj),
GET_OBJ_COST_PER_DAY(obj), GET_OBJ_LEVEL(obj), GET_OBJ_TIMER(obj)
);
fputs("]\n", fp);
fprintf(fp, "weight = %d\n", GET_OBJ_WEIGHT(obj));
fprintf(fp, "cost = %d\n", GET_OBJ_COST(obj));
fprintf(fp, "level = %d\n", GET_OBJ_LEVEL(obj));
fprintf(fp, "timer = %d\n", GET_OBJ_TIMER(obj));
/* Do we have script(s) attached? */
script_save_to_disk(fp, obj, OBJ_TRIGGER);
@ -272,24 +249,25 @@ int save_objects(zone_rnum zone_num)
}
strncpy(buf, ex_desc->description, sizeof(buf) - 1);
strip_cr(buf);
fprintf(fp, "E\n"
"%s~\n"
"%s~\n", ex_desc->keyword, buf);
fprintf(fp, "\n[[object.extra_desc]]\n");
toml_write_kv_string(fp, "keyword", ex_desc->keyword);
toml_write_kv_string(fp, "description", buf);
}
}
/* Do we have affects? */
for (counter2 = 0; counter2 < MAX_OBJ_AFFECT; counter2++)
if (obj->affected[counter2].modifier)
fprintf(fp, "A\n"
"%d %d\n", obj->affected[counter2].location,
obj->affected[counter2].modifier);
for (counter2 = 0; counter2 < MAX_OBJ_AFFECT; counter2++) {
if (obj->affected[counter2].modifier) {
fprintf(fp, "\n[[object.affect]]\n");
fprintf(fp, "location = %d\n", obj->affected[counter2].location);
fprintf(fp, "modifier = %d\n", obj->affected[counter2].modifier);
}
}
fputc('\n', fp);
}
}
/* Write the final line, close the file. */
fprintf(fp, "$~\n");
fclose(fp);
snprintf(buf, sizeof(buf), "%s/%d.obj", OBJ_PREFIX, zone_table[zone_num].number);
snprintf(buf, sizeof(buf), "%s/%d.toml", OBJ_PREFIX, zone_table[zone_num].number);
remove(buf);
rename(filename, buf);
@ -615,4 +593,4 @@ void clamp_armor_values(struct obj_data *obj) {
GET_OBJ_VAL(obj, VAL_ARMOR_MAGIC_BONUS) = v;
/* flags are a bitvector; leave as-is (OLC will manage legal bits) */
}
}

View file

@ -313,7 +313,7 @@ ACMD(do_export_zone)
#else /* all other configurations */
zone_rnum zrnum;
zone_vnum zvnum;
char sysbuf[MAX_INPUT_LENGTH];
char sysbuf[MAX_STRING_LENGTH];
char zone_name[READ_SIZE], fixed_file_name[READ_SIZE];
int success, errorcode = 0;
@ -384,7 +384,7 @@ ACMD(do_export_zone)
/* Tar the new copy. */
snprintf(sysbuf, sizeof(sysbuf), "tar -cf %s%s.tar %sqq.info %sqq.wld %sqq.zon %sqq.mob %sqq.obj %sqq.trg %sqq.shp", path, fixed_file_name, path, path, path, path, path, path, path);
snprintf(sysbuf, sizeof(sysbuf), "tar -cf %s%s.tar %sqq.info %sqq.wld.toml %sqq.zon.toml %sqq.mob.toml %sqq.obj.toml %sqq.trg.toml %sqq.shp.toml %sqq.qst.toml", path, fixed_file_name, path, path, path, path, path, path, path, path);
errorcode = system(sysbuf);
if (errorcode) {
send_to_char(ch, "Failed to tar files.\r\n");
@ -425,8 +425,8 @@ static int export_info_file(zone_rnum zrnum)
fprintf(info_file, "Implementation:\n");
fprintf(info_file, "1. All the files have been QQ'ed. This means all occurences of the zone number\n");
fprintf(info_file, " have been changed to QQ. In other words, if you decide to have this zone as\n");
fprintf(info_file, " zone 123, replace all occurences of QQ with 123 and rename the qq.zon file\n");
fprintf(info_file, " to 123.zon (etc.). And of course add 123.zon to the respective index file.\n");
fprintf(info_file, " zone 123, replace all occurences of QQ with 123 and rename the qq.wld.toml file\n");
fprintf(info_file, " to 123.toml (etc.). And of course add 123.toml to the respective index file.\n");
if (zone_exits) {
fprintf(info_file, "2. Exits out of this zone have been ZZ'd. So all doors leading out have ZZ??\n");
fprintf(info_file, " instead of the room vnum (?? are numbers 00 - 99).\n");
@ -481,7 +481,7 @@ static int export_save_shops(zone_rnum zrnum)
FILE *shop_file;
struct shop_data *shop;
if (!(shop_file = fopen("world/export/qq.shp", "w"))) {
if (!(shop_file = fopen("world/export/qq.shp.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_shops : Cannot open shop file!");
return FALSE;
} else if (fprintf(shop_file, "CircleMUD v3.0 Shop File~\n") < 0) {
@ -571,7 +571,7 @@ static int export_save_mobiles(zone_rnum rznum)
mob_vnum i;
mob_rnum rmob;
if (!(mob_file = fopen("world/export/qq.mob", "w"))) {
if (!(mob_file = fopen("world/export/qq.mob.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_mobiles : Cannot open file!");
return FALSE;
}
@ -648,7 +648,7 @@ static int export_save_zone(zone_rnum zrnum)
int subcmd;
FILE *zone_file;
if (!(zone_file = fopen("world/export/qq.zon", "w"))) {
if (!(zone_file = fopen("world/export/qq.zon.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_zone : Cannot open file!");
return FALSE;
}
@ -783,7 +783,7 @@ static int export_save_objects(zone_rnum zrnum)
struct obj_data *obj;
struct extra_descr_data *ex_desc;
if (!(obj_file = fopen("world/export/qq.obj", "w"))) {
if (!(obj_file = fopen("world/export/qq.obj.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_objects : Cannot open file!");
return FALSE;
}
@ -889,7 +889,7 @@ static int export_save_rooms(zone_rnum zrnum)
char buf[MAX_STRING_LENGTH];
char buf1[MAX_STRING_LENGTH];
if (!(room_file = fopen("world/export/qq.wld", "w"))) {
if (!(room_file = fopen("world/export/qq.wld.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_rooms : Cannot open file!");
return FALSE;
}
@ -1028,7 +1028,7 @@ static int export_save_triggers(zone_rnum zrnum)
FILE *trig_file;
char bitBuf[MAX_INPUT_LENGTH];
if (!(trig_file = fopen("world/export/qq.trg", "w"))) {
if (!(trig_file = fopen("world/export/qq.trg.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_triggers : Cannot open file!");
return FALSE;
}

View file

@ -16,6 +16,7 @@
#include "quest.h"
#include "genolc.h"
#include "genzon.h" /* for create_world_index */
#include "toml_utils.h"
/*-------------------------------------------------------------------*/
@ -176,10 +177,9 @@ int delete_quest(qst_rnum rnum)
int save_quests(zone_rnum zone_num)
{
FILE *sf;
char filename[128], oldname[128], quest_flags[MAX_STRING_LENGTH];
char filename[128], oldname[128];
char quest_desc[MAX_STRING_LENGTH], quest_info[MAX_STRING_LENGTH];
char quest_done[MAX_STRING_LENGTH], quest_quit[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
int i, num_quests = 0;
#if CIRCLE_UNSIGNED_INDEX
@ -219,53 +219,37 @@ int save_quests(zone_rnum zone_num)
strip_cr(quest_done);
strip_cr(quest_quit);
/* Save the quest details to the file. */
sprintascii(quest_flags, QST_FLAGS(rnum));
int n = snprintf(buf, MAX_STRING_LENGTH,
"#%d\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%d %d %s %d %d %d %d\n"
"%d %d %d %d %d %d %d\n"
"%d %d %d\n"
"S\n",
QST_NUM(rnum),
QST_NAME(rnum) ? QST_NAME(rnum) : "Untitled", STRING_TERMINATOR,
quest_desc, STRING_TERMINATOR,
quest_info, STRING_TERMINATOR,
quest_done, STRING_TERMINATOR,
quest_quit, STRING_TERMINATOR,
QST_TYPE(rnum),
QST_MASTER(rnum) == NOBODY ? -1 : QST_MASTER(rnum),
quest_flags,
QST_TARGET(rnum) == NOTHING ? -1 : QST_TARGET(rnum),
QST_PREV(rnum) == NOTHING ? -1 : QST_PREV(rnum),
QST_NEXT(rnum) == NOTHING ? -1 : QST_NEXT(rnum),
QST_PREREQ(rnum) == NOTHING ? -1 : QST_PREREQ(rnum),
QST_POINTS(rnum), QST_PENALTY(rnum), QST_MINLEVEL(rnum),
QST_MAXLEVEL(rnum), QST_TIME(rnum),
QST_RETURNMOB(rnum) == NOBODY ? -1 : QST_RETURNMOB(rnum),
QST_QUANTITY(rnum), QST_COINS(rnum), QST_EXP(rnum), QST_OBJ(rnum)
);
if(n < MAX_STRING_LENGTH) {
fprintf(sf, "%s", convert_from_tabs(buf));
num_quests++;
} else {
mudlog(BRF,LVL_BUILDER,TRUE,
"SYSERR: Could not save quest #%d due to size (%d > maximum of %d).",
QST_NUM(rnum), n, MAX_STRING_LENGTH);
}
fprintf(sf, "[[quest]]\n");
fprintf(sf, "vnum = %d\n", QST_NUM(rnum));
toml_write_kv_string(sf, "name", QST_NAME(rnum) ? QST_NAME(rnum) : "Untitled");
toml_write_kv_string(sf, "description", quest_desc);
toml_write_kv_string(sf, "info", quest_info);
toml_write_kv_string(sf, "done", quest_done);
toml_write_kv_string(sf, "quit", quest_quit);
fprintf(sf, "type = %d\n", QST_TYPE(rnum));
fprintf(sf, "quest_master = %d\n", QST_MASTER(rnum) == NOBODY ? -1 : QST_MASTER(rnum));
fprintf(sf, "flags = %d\n", (int)QST_FLAGS(rnum));
fprintf(sf, "target = %d\n", QST_TARGET(rnum) == NOTHING ? -1 : QST_TARGET(rnum));
fprintf(sf, "prev_quest = %d\n", QST_PREV(rnum) == NOTHING ? -1 : QST_PREV(rnum));
fprintf(sf, "next_quest = %d\n", QST_NEXT(rnum) == NOTHING ? -1 : QST_NEXT(rnum));
fprintf(sf, "prereq = %d\n", QST_PREREQ(rnum) == NOTHING ? -1 : QST_PREREQ(rnum));
fprintf(sf, "values = [%d, %d, %d, %d, %d, %d, %d]\n",
QST_POINTS(rnum), QST_PENALTY(rnum), QST_MINLEVEL(rnum),
QST_MAXLEVEL(rnum), QST_TIME(rnum),
QST_RETURNMOB(rnum) == NOBODY ? -1 : QST_RETURNMOB(rnum),
QST_QUANTITY(rnum));
fprintf(sf, "[quest.rewards]\n");
fprintf(sf, "coins = %d\n", QST_COINS(rnum));
fprintf(sf, "exp = %d\n", QST_EXP(rnum));
fprintf(sf, "obj_vnum = %d\n", QST_OBJ(rnum) == NOTHING ? -1 : QST_OBJ(rnum));
fputc('\n', sf);
num_quests++;
}
}
/* Write the final line and close it. */
fprintf(sf, "$~\n");
fclose(sf);
/* Old file we're replacing. */
snprintf(oldname, sizeof(oldname), "%s/%d.qst",
snprintf(oldname, sizeof(oldname), "%s/%d.toml",
QST_PREFIX, zone_table[zone_num].number);
remove(oldname);
rename(filename, oldname);

View file

@ -14,6 +14,7 @@
#include "genolc.h"
#include "genshp.h"
#include "genzon.h"
#include "toml_utils.h"
/* NOTE (gg): Didn't modify sedit much. Don't consider it as 'recent' as the
* other editors with regard to updates or style. */
@ -345,7 +346,7 @@ int save_shops(zone_rnum zone_num)
{
int i, j, rshop, num_shops = 0;
FILE *shop_file;
char fname[128], oldname[128], buf[MAX_STRING_LENGTH];
char fname[128], oldname[128];
struct shop_data *shop;
#if CIRCLE_UNSIGNED_INDEX
@ -361,77 +362,68 @@ int save_shops(zone_rnum zone_num)
if (!(shop_file = fopen(fname, "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: OLC: Cannot open shop file!");
return FALSE;
} else if (fprintf(shop_file, "CircleMUD v3.0 Shop File~\n") < 0) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: OLC: Cannot write to shop file!");
fclose(shop_file);
return FALSE;
}
/* Search database for shops in this zone. */
for (i = genolc_zone_bottom(zone_num); i <= zone_table[zone_num].top; i++) {
if ((rshop = real_shop(i)) != NOWHERE) {
fprintf(shop_file, "#%d~\n", i);
shop = shop_index + rshop;
/* Save the products. */
for (j = 0; S_PRODUCT(shop, j) != NOTHING; j++)
fprintf(shop_file, "%d\n", obj_index[S_PRODUCT(shop, j)].vnum);
fprintf(shop_file, "-1\n");
fprintf(shop_file, "[[shop]]\n");
fprintf(shop_file, "vnum = %d\n", i);
/* Save the rates. */
fprintf(shop_file, "%1.2f\n"
"%1.2f\n",
S_BUYPROFIT(shop),
S_SELLPROFIT(shop));
fprintf(shop_file, "products = [");
for (j = 0; S_PRODUCT(shop, j) != NOTHING; j++) {
if (j)
fputs(", ", shop_file);
fprintf(shop_file, "%d", obj_index[S_PRODUCT(shop, j)].vnum);
}
fputs("]\n", shop_file);
/* Save the buy types and namelists. */
for (j = 0;S_BUYTYPE(shop, j) != NOTHING; j++)
fprintf(shop_file, "%d%s\n",
S_BUYTYPE(shop, j),
S_BUYWORD(shop, j) ? S_BUYWORD(shop, j) : "");
fprintf(shop_file, "-1\n");
fprintf(shop_file, "buy_profit = %1.2f\n", S_BUYPROFIT(shop));
fprintf(shop_file, "sell_profit = %1.2f\n", S_SELLPROFIT(shop));
/* Save messages. Added some defaults as sanity checks. */
sprintf(buf,
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%d\n"
"%ld\n"
"%d\n"
"%d\n",
S_NOITEM1(shop) ? S_NOITEM1(shop) : "%s Ke?!",
S_NOITEM2(shop) ? S_NOITEM2(shop) : "%s Ke?!",
S_NOBUY(shop) ? S_NOBUY(shop) : "%s Ke?!",
S_NOCASH1(shop) ? S_NOCASH1(shop) : "%s Ke?!",
S_NOCASH2(shop) ? S_NOCASH2(shop) : "%s Ke?!",
S_BUY(shop) ? S_BUY(shop) : "%s Ke?! %d?",
S_SELL(shop) ? S_SELL(shop) : "%s Ke?! %d?",
S_BROKE_TEMPER(shop),
S_BITVECTOR(shop),
S_KEEPER(shop) == NOBODY ? -1 : mob_index[S_KEEPER(shop)].vnum,
S_NOTRADE(shop)
);
fputs(convert_from_tabs(buf), shop_file);
for (j = 0; S_BUYTYPE(shop, j) != NOTHING; j++) {
fprintf(shop_file, "\n[[shop.buy_type]]\n");
fprintf(shop_file, "type = %d\n", S_BUYTYPE(shop, j));
toml_write_kv_string_opt(shop_file, "keyword", S_BUYWORD(shop, j));
}
/* Save the rooms. */
for (j = 0;S_ROOM(shop, j) != NOWHERE; j++)
fprintf(shop_file, "%d\n", S_ROOM(shop, j));
fprintf(shop_file, "-1\n");
fprintf(shop_file, "\n[shop.messages]\n");
toml_write_kv_string(shop_file, "no_such_item1", S_NOITEM1(shop) ? S_NOITEM1(shop) : "");
toml_write_kv_string(shop_file, "no_such_item2", S_NOITEM2(shop) ? S_NOITEM2(shop) : "");
toml_write_kv_string(shop_file, "do_not_buy", S_NOBUY(shop) ? S_NOBUY(shop) : "");
toml_write_kv_string(shop_file, "missing_cash1", S_NOCASH1(shop) ? S_NOCASH1(shop) : "");
toml_write_kv_string(shop_file, "missing_cash2", S_NOCASH2(shop) ? S_NOCASH2(shop) : "");
toml_write_kv_string(shop_file, "message_buy", S_BUY(shop) ? S_BUY(shop) : "");
toml_write_kv_string(shop_file, "message_sell", S_SELL(shop) ? S_SELL(shop) : "");
/* Save open/closing times. */
fprintf(shop_file, "%d\n%d\n%d\n%d\n", S_OPEN1(shop), S_CLOSE1(shop),
S_OPEN2(shop), S_CLOSE2(shop));
fprintf(shop_file, "broke_temper = %d\n", S_BROKE_TEMPER(shop));
fprintf(shop_file, "bitvector = %ld\n", S_BITVECTOR(shop));
fprintf(shop_file, "keeper = %d\n",
S_KEEPER(shop) == NOBODY ? -1 : mob_index[S_KEEPER(shop)].vnum);
fprintf(shop_file, "trade_with = %d\n", S_NOTRADE(shop));
fprintf(shop_file, "rooms = [");
for (j = 0; S_ROOM(shop, j) != NOWHERE; j++) {
if (j)
fputs(", ", shop_file);
fprintf(shop_file, "%d", S_ROOM(shop, j));
}
fputs("]\n", shop_file);
fprintf(shop_file, "open1 = %d\n", S_OPEN1(shop));
fprintf(shop_file, "close1 = %d\n", S_CLOSE1(shop));
fprintf(shop_file, "open2 = %d\n", S_OPEN2(shop));
fprintf(shop_file, "close2 = %d\n", S_CLOSE2(shop));
fprintf(shop_file, "bank = %d\n", S_BANK(shop));
fprintf(shop_file, "sort = %d\n", S_SORT(shop));
fputc('\n', shop_file);
num_shops++;
}
}
fprintf(shop_file, "$~\n");
fclose(shop_file);
snprintf(oldname, sizeof(oldname), "%s/%d.shp", SHP_PREFIX, zone_table[zone_num].number);
snprintf(oldname, sizeof(oldname), "%s/%d.toml", SHP_PREFIX, zone_table[zone_num].number);
remove(oldname);
rename(fname, oldname);

View file

@ -18,6 +18,7 @@
#include "shop.h"
#include "dg_olc.h"
#include "mud_event.h"
#include "toml_utils.h"
/* This function will copy the strings so be sure you free your own copies of
@ -269,7 +270,6 @@ int save_rooms(zone_rnum rzone)
char filename[128];
char buf[MAX_STRING_LENGTH];
char buf1[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
#if CIRCLE_UNSIGNED_INDEX
if (rzone == NOWHERE || rzone > top_of_zone_table) {
@ -301,96 +301,70 @@ int save_rooms(zone_rnum rzone)
strncpy(buf, room->description ? room->description : "Empty room.", sizeof(buf)-1 );
strip_cr(buf);
/* Save the numeric and string section of the file. */
int n = snprintf(buf2, MAX_STRING_LENGTH, "#%d\n"
"%s%c\n"
"%s%c\n"
"%d %d %d %d %d %d\n",
room->number,
room->name ? room->name : "Untitled", STRING_TERMINATOR,
buf, STRING_TERMINATOR,
zone_table[room->zone].number, room->room_flags[0], room->room_flags[1], room->room_flags[2],
room->room_flags[3], room->sector_type
);
if(n >= MAX_STRING_LENGTH) {
mudlog(BRF,LVL_BUILDER,TRUE,
"SYSERR: Could not save room #%d due to size (%d > maximum of %d).",
room->number, n, MAX_STRING_LENGTH);
continue;
}
fprintf(sf, "[[room]]\n");
fprintf(sf, "vnum = %d\n", room->number);
toml_write_kv_string(sf, "name", room->name ? convert_from_tabs(room->name) : "Untitled");
toml_write_kv_string(sf, "description", convert_from_tabs(buf));
fprintf(sf, "flags = [%d, %d, %d, %d]\n",
room->room_flags[0], room->room_flags[1],
room->room_flags[2], room->room_flags[3]);
fprintf(sf, "sector = %d\n", room->sector_type);
fprintf(sf, "%s", convert_from_tabs(buf2));
/* Now you write out the exits for the room. */
for (j = 0; j < DIR_COUNT; j++) {
if (R_EXIT(room, j)) {
int dflag;
if (R_EXIT(room, j)->general_description) {
strncpy(buf, R_EXIT(room, j)->general_description, sizeof(buf)-1);
strip_cr(buf);
} else
*buf = '\0';
if (R_EXIT(room, j)) {
if (R_EXIT(room, j)->general_description) {
strncpy(buf, R_EXIT(room, j)->general_description, sizeof(buf)-1);
strip_cr(buf);
} else
*buf = '\0';
/* Figure out door flag. */
if (IS_SET(R_EXIT(room, j)->exit_info, EX_ISDOOR)) {
if (IS_SET(R_EXIT(room, j)->exit_info, EX_PICKPROOF))
dflag = 2;
else
dflag = 1;
if (IS_SET(R_EXIT(room, j)->exit_info, EX_HIDDEN))
dflag += 2;
} else
dflag = 0;
if (R_EXIT(room, j)->keyword)
strncpy(buf1, R_EXIT(room, j)->keyword, sizeof(buf1)-1 );
else
*buf1 = '\0';
if (R_EXIT(room, j)->keyword)
strncpy(buf1, R_EXIT(room, j)->keyword, sizeof(buf1)-1 );
else
*buf1 = '\0';
/* Now write the exit to the file. */
fprintf(sf, "D%d\n"
"%s~\n"
"%s~\n"
"%d %d %d\n", j, buf, buf1, dflag,
R_EXIT(room, j)->key != NOTHING ? R_EXIT(room, j)->key : -1,
R_EXIT(room, j)->to_room != NOWHERE ? world[R_EXIT(room, j)->to_room].number : -1);
}
fprintf(sf, "\n[[room.exit]]\n");
fprintf(sf, "dir = %d\n", j);
toml_write_kv_string(sf, "description", convert_from_tabs(buf));
toml_write_kv_string(sf, "keyword", buf1);
fprintf(sf, "exit_info = %d\n", R_EXIT(room, j)->exit_info);
fprintf(sf, "key = %d\n",
R_EXIT(room, j)->key != NOTHING ? R_EXIT(room, j)->key : -1);
fprintf(sf, "to_room = %d\n",
R_EXIT(room, j)->to_room != NOWHERE ? world[R_EXIT(room, j)->to_room].number : -1);
}
}
if (room->ex_description) {
struct extra_descr_data *xdesc;
for (xdesc = room->ex_description; xdesc; xdesc = xdesc->next) {
strncpy(buf, xdesc->description, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
strip_cr(buf);
fprintf(sf, "E\n"
"%s~\n"
"%s~\n", xdesc->keyword, buf);
}
for (xdesc = room->ex_description; xdesc; xdesc = xdesc->next) {
strncpy(buf, xdesc->description, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
strip_cr(buf);
fprintf(sf, "\n[[room.extra_desc]]\n");
toml_write_kv_string(sf, "keyword", xdesc->keyword);
toml_write_kv_string(sf, "description", convert_from_tabs(buf));
}
}
if (room->forage) {
struct forage_entry *entry;
fprintf(sf, "F\n");
for (entry = room->forage; entry; entry = entry->next)
fprintf(sf, "%d %d\n", entry->obj_vnum, entry->dc);
fprintf(sf, "0 0\n");
for (entry = room->forage; entry; entry = entry->next) {
fprintf(sf, "\n[[room.forage]]\n");
fprintf(sf, "obj_vnum = %d\n", entry->obj_vnum);
fprintf(sf, "dc = %d\n", entry->dc);
}
}
fprintf(sf, "S\n");
script_save_to_disk(sf, room, WLD_TRIGGER);
fputc('\n', sf);
}
}
/* Write the final line and close it. */
fprintf(sf, "$~\n");
fclose(sf);
/* Old file we're replacing. */
snprintf(buf, sizeof(buf), "%s/%d.wld", WLD_PREFIX, zone_table[rzone].number);
snprintf(buf, sizeof(buf), "%s/%d.toml", WLD_PREFIX, zone_table[rzone].number);
remove(buf);
rename(filename, buf);

View file

@ -11,6 +11,8 @@
#include "utils.h"
#include "db.h"
#include "genolc.h"
#include "toml.h"
#include "toml_utils.h"
#include "genzon.h"
#include "dg_scripts.h"
@ -89,7 +91,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
}
/* Create the zone file. */
snprintf(buf, sizeof(buf), "%s/%d.zon", ZON_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", ZON_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new zone file.");
*error = "Could not write zone file.\r\n";
@ -99,7 +101,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the room file. */
snprintf(buf, sizeof(buf), "%s/%d.wld", WLD_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", WLD_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new world file.");
*error = "Could not write world file.\r\n";
@ -109,7 +111,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the mobile file. */
snprintf(buf, sizeof(buf), "%s/%d.mob", MOB_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", MOB_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new mob file.");
*error = "Could not write mobile file.\r\n";
@ -119,7 +121,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the object file. */
snprintf(buf, sizeof(buf), "%s/%d.obj", OBJ_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", OBJ_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new obj file.");
*error = "Could not write object file.\r\n";
@ -129,7 +131,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the shop file. */
snprintf(buf, sizeof(buf), "%s/%d.shp", SHP_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", SHP_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new shop file.");
*error = "Could not write shop file.\r\n";
@ -139,7 +141,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the quests file */
snprintf(buf, sizeof(buf), "%s/%d.qst", QST_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", QST_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new quest file");
*error = "Could not write quest file.\r\n";
@ -149,7 +151,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the trigger file. */
snprintf(buf, sizeof(buf), "%s/%d.trg", TRG_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", TRG_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new trigger file");
*error = "Could not write trigger file.\r\n";
@ -219,9 +221,12 @@ void create_world_index(int znum, const char *type)
{
FILE *newfile, *oldfile;
char new_name[32], old_name[32], *prefix;
int num, found = FALSE;
char buf[MAX_STRING_LENGTH];
char buf1[MAX_STRING_LENGTH];
char **files = NULL;
char errbuf[256];
char file_name[32];
toml_table_t *tab = NULL;
toml_array_t *arr = NULL;
int i, num, count, insert_at;
switch (*type) {
case 'z':
@ -250,44 +255,98 @@ void create_world_index(int znum, const char *type)
return;
}
snprintf(old_name, sizeof(old_name), "%s/index", prefix);
snprintf(new_name, sizeof(new_name), "%s/newindex", prefix);
snprintf(old_name, sizeof(old_name), "%s/index.toml", prefix);
snprintf(new_name, sizeof(new_name), "%s/newindex.toml", prefix);
snprintf(file_name, sizeof(file_name), "%d.toml", znum);
if (!(oldfile = fopen(old_name, "r"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to open %s.", old_name);
return;
} else if (!(newfile = fopen(new_name, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to open %s.", new_name);
fclose(oldfile);
}
tab = toml_parse_file(oldfile, errbuf, sizeof(errbuf));
fclose(oldfile);
if (!tab) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to parse %s: %s.", old_name, errbuf);
return;
}
/* Index contents must be in order: search through the old file for the right
* place, insert the new file, then copy the rest over. */
snprintf(buf1, sizeof(buf1), "%d.%s", znum, type);
while (get_line(oldfile, buf)) {
if (*buf == '$') {
/* The following used to add a blank line, thanks to Brian Taylor for the fix. */
fprintf(newfile, "%s", (!found ? strncat(buf1, "\n$\n", sizeof(buf1) - strlen(buf1) - 1) : "$\n"));
break;
} else if (!found) {
sscanf(buf, "%d", &num);
if (num > znum) {
found = TRUE;
fprintf(newfile, "%s\n", buf1);
} else if (num == znum) {
/* index file already had an entry for this zone. */
fclose(oldfile);
fclose(newfile);
remove(new_name);
return;
}
}
fprintf(newfile, "%s\n", buf);
arr = toml_array_in(tab, "files");
if (!arr) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: %s missing 'files' array.", old_name);
toml_free(tab);
return;
}
count = toml_array_nelem(arr);
CREATE(files, char *, count + 1);
for (i = 0; i < count; i++) {
toml_datum_t d = toml_string_at(arr, i);
if (!d.ok) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: %s has invalid 'files' entry at %d.", old_name, i);
toml_free(tab);
while (i-- > 0)
free(files[i]);
free(files);
return;
}
files[i] = d.u.s;
}
for (i = 0; i < count; i++) {
if (!strcmp(files[i], file_name)) {
toml_free(tab);
for (i = 0; i < count; i++)
free(files[i]);
free(files);
return;
}
if (sscanf(files[i], "%d", &num) == 1 && num == znum) {
toml_free(tab);
for (i = 0; i < count; i++)
free(files[i]);
free(files);
return;
}
}
insert_at = count;
for (i = 0; i < count; i++) {
if (sscanf(files[i], "%d", &num) == 1 && num > znum) {
insert_at = i;
break;
}
}
RECREATE(files, char *, count + 2);
if (insert_at < count)
memmove(&files[insert_at + 1], &files[insert_at], sizeof(char *) * (count - insert_at));
files[insert_at] = strdup(file_name);
count++;
if (!(newfile = fopen(new_name, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to open %s.", new_name);
toml_free(tab);
for (i = 0; i < count; i++)
free(files[i]);
free(files);
return;
}
fprintf(newfile, "files = [\n");
for (i = 0; i < count; i++) {
fprintf(newfile, " ");
toml_write_string(newfile, files[i]);
fprintf(newfile, "%s\n", (i + 1 < count) ? "," : "");
}
fprintf(newfile, "]\n");
fclose(newfile);
fclose(oldfile);
toml_free(tab);
for (i = 0; i < count; i++)
free(files[i]);
free(files);
/* Out with the old, in with the new. */
remove(old_name);
rename(new_name, old_name);
@ -326,12 +385,9 @@ void remove_room_zone_commands(zone_rnum zone, room_rnum room_num)
* field is also there. */
int save_zone(zone_rnum zone_num)
{
int subcmd, arg1 = -1, arg2 = -1, arg3 = -1, flag_tot=0, i;
int subcmd, arg1 = -1, arg2 = -1, arg3 = -1;
char fname[128], oldname[128];
const char *comment = NULL;
FILE *zfile;
char zbuf1[MAX_STRING_LENGTH], zbuf2[MAX_STRING_LENGTH];
char zbuf3[MAX_STRING_LENGTH], zbuf4[MAX_STRING_LENGTH];
#if CIRCLE_UNSIGNED_INDEX
if (zone_num == NOWHERE || zone_num > top_of_zone_table) {
@ -348,67 +404,25 @@ int save_zone(zone_rnum zone_num)
return FALSE;
}
for (i=0; i<ZN_ARRAY_MAX; i++)
flag_tot += zone_table[zone_num].zone_flags[(i)];
/* If zone flags or levels aren't set, there is no reason to save them! */
if (flag_tot == 0 && zone_table[zone_num].min_level == -1 && zone_table[zone_num].max_level == -1)
{
/* Print zone header to file. */
fprintf(zfile, "#%d\n"
"%s~\n"
"%s~\n"
"%d %d %d %d\n",
zone_table[zone_num].number,
(zone_table[zone_num].builders && *zone_table[zone_num].builders)
? zone_table[zone_num].builders : "None.",
(zone_table[zone_num].name && *zone_table[zone_num].name)
? convert_from_tabs(zone_table[zone_num].name) : "undefined",
genolc_zone_bottom(zone_num),
zone_table[zone_num].top,
zone_table[zone_num].lifespan,
zone_table[zone_num].reset_mode
);
} else {
sprintascii(zbuf1, zone_table[zone_num].zone_flags[0]);
sprintascii(zbuf2, zone_table[zone_num].zone_flags[1]);
sprintascii(zbuf3, zone_table[zone_num].zone_flags[2]);
sprintascii(zbuf4, zone_table[zone_num].zone_flags[3]);
/* Print zone header to file. */
fprintf(zfile, "#%d\n"
"%s~\n"
"%s~\n"
"%d %d %d %d %s %s %s %s %d %d\n", /* New tbaMUD data line */
zone_table[zone_num].number,
(zone_table[zone_num].builders && *zone_table[zone_num].builders)
? zone_table[zone_num].builders : "None.",
(zone_table[zone_num].name && *zone_table[zone_num].name)
? convert_from_tabs(zone_table[zone_num].name) : "undefined",
genolc_zone_bottom(zone_num),
zone_table[zone_num].top,
zone_table[zone_num].lifespan,
zone_table[zone_num].reset_mode,
zbuf1, zbuf2, zbuf3, zbuf4,
zone_table[zone_num].min_level,
zone_table[zone_num].max_level
);
}
/* Handy Quick Reference Chart for Zone Values.
*
* Field #1 Field #3 Field #4 Field #5
* -------------------------------------------------
* M (Mobile) Mob-Vnum Wld-Max Room-Vnum
* O (Object) Obj-Vnum Wld-Max Room-Vnum
* G (Give) Obj-Vnum Wld-Max Unused
* E (Equip) Obj-Vnum Wld-Max EQ-Position
* P (Put) Obj-Vnum Wld-Max Target-Obj-Vnum
* D (Door) Room-Vnum Door-Dir Door-State
* R (Remove) Room-Vnum Obj-Vnum Unused
* T (Trigger) Trig-type Trig-Vnum Room-Vnum
* V (var) Trig-type Context Room-Vnum Varname Value
* ------------------------------------------------- */
fprintf(zfile, "[[zone]]\n");
fprintf(zfile, "vnum = %d\n", zone_table[zone_num].number);
toml_write_kv_string(zfile, "builders",
(zone_table[zone_num].builders && *zone_table[zone_num].builders)
? zone_table[zone_num].builders : "None.");
toml_write_kv_string(zfile, "name",
(zone_table[zone_num].name && *zone_table[zone_num].name)
? convert_from_tabs(zone_table[zone_num].name) : "undefined");
fprintf(zfile, "bot = %d\n", genolc_zone_bottom(zone_num));
fprintf(zfile, "top = %d\n", zone_table[zone_num].top);
fprintf(zfile, "lifespan = %d\n", zone_table[zone_num].lifespan);
fprintf(zfile, "reset_mode = %d\n", zone_table[zone_num].reset_mode);
fprintf(zfile, "flags = [%d, %d, %d, %d]\n",
zone_table[zone_num].zone_flags[0],
zone_table[zone_num].zone_flags[1],
zone_table[zone_num].zone_flags[2],
zone_table[zone_num].zone_flags[3]);
fprintf(zfile, "min_level = %d\n", zone_table[zone_num].min_level);
fprintf(zfile, "max_level = %d\n", zone_table[zone_num].max_level);
for (subcmd = 0; ZCMD(zone_num, subcmd).command != 'S'; subcmd++) {
switch (ZCMD(zone_num, subcmd).command) {
@ -416,49 +430,41 @@ int save_zone(zone_rnum zone_num)
arg1 = mob_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = world[ZCMD(zone_num, subcmd).arg3].number;
comment = mob_proto[ZCMD(zone_num, subcmd).arg1].player.short_descr;
break;
case 'O':
arg1 = obj_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = world[ZCMD(zone_num, subcmd).arg3].number;
comment = obj_proto[ZCMD(zone_num, subcmd).arg1].short_description;
break;
case 'G':
arg1 = obj_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = -1;
comment = obj_proto[ZCMD(zone_num, subcmd).arg1].short_description;
break;
case 'E':
arg1 = obj_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = ZCMD(zone_num, subcmd).arg3;
comment = obj_proto[ZCMD(zone_num, subcmd).arg1].short_description;
break;
case 'P':
arg1 = obj_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = obj_index[ZCMD(zone_num, subcmd).arg3].vnum;
comment = obj_proto[ZCMD(zone_num, subcmd).arg1].short_description;
break;
case 'D':
arg1 = world[ZCMD(zone_num, subcmd).arg1].number;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = ZCMD(zone_num, subcmd).arg3;
comment = world[ZCMD(zone_num, subcmd).arg1].name;
break;
case 'R':
arg1 = world[ZCMD(zone_num, subcmd).arg1].number;
arg2 = obj_index[ZCMD(zone_num, subcmd).arg2].vnum;
comment = obj_proto[ZCMD(zone_num, subcmd).arg2].short_description;
arg3 = -1;
break;
case 'T':
arg1 = ZCMD(zone_num, subcmd).arg1; /* trigger type */
arg2 = trig_index[ZCMD(zone_num, subcmd).arg2]->vnum; /* trigger vnum */
arg3 = world[ZCMD(zone_num, subcmd).arg3].number; /* room num */
comment = GET_TRIG_NAME(trig_index[real_trigger(arg2)]->proto);
break;
case 'V':
arg1 = ZCMD(zone_num, subcmd).arg1; /* trigger type */
@ -472,17 +478,20 @@ int save_zone(zone_rnum zone_num)
mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: z_save_to_disk(): Unknown cmd '%c' - NOT saving", ZCMD(zone_num, subcmd).command);
continue;
}
if (ZCMD(zone_num, subcmd).command != 'V')
fprintf(zfile, "%c %d %d %d %d \t(%s)\n",
ZCMD(zone_num, subcmd).command, ZCMD(zone_num, subcmd).if_flag, arg1, arg2, arg3, comment);
else
fprintf(zfile, "%c %d %d %d %d %s %s\n",
ZCMD(zone_num, subcmd).command, ZCMD(zone_num, subcmd).if_flag, arg1, arg2, arg3,
ZCMD(zone_num, subcmd).sarg1, ZCMD(zone_num, subcmd).sarg2);
fprintf(zfile, "\n[[zone.command]]\n");
fprintf(zfile, "command = \"%c\"\n", ZCMD(zone_num, subcmd).command);
fprintf(zfile, "if_flag = %d\n", ZCMD(zone_num, subcmd).if_flag);
fprintf(zfile, "arg1 = %d\n", arg1);
fprintf(zfile, "arg2 = %d\n", arg2);
fprintf(zfile, "arg3 = %d\n", arg3);
if (ZCMD(zone_num, subcmd).command == 'V') {
toml_write_kv_string(zfile, "sarg1", ZCMD(zone_num, subcmd).sarg1 ? ZCMD(zone_num, subcmd).sarg1 : "");
toml_write_kv_string(zfile, "sarg2", ZCMD(zone_num, subcmd).sarg2 ? ZCMD(zone_num, subcmd).sarg2 : "");
}
fprintf(zfile, "line = %d\n", ZCMD(zone_num, subcmd).line);
}
fputs("S\n$\n", zfile);
fclose(zfile);
snprintf(oldname, sizeof(oldname), "%s/%d.zon", ZON_PREFIX, zone_table[zone_num].number);
snprintf(oldname, sizeof(oldname), "%s/%d.toml", ZON_PREFIX, zone_table[zone_num].number);
remove(oldname);
rename(fname, oldname);
@ -586,4 +595,3 @@ void delete_zone_command(struct zone_data *zone, int pos)
/* Ok, let's zap it. */
remove_cmd_from_list(&zone->cmd, pos);
}

View file

@ -48,7 +48,7 @@ static int House_get_filename(room_vnum vnum, char *filename, size_t maxlen)
if (vnum == NOWHERE)
return (0);
snprintf(filename, maxlen, LIB_HOUSE"%d.house", vnum);
snprintf(filename, maxlen, LIB_HOUSE"%d.house.toml", vnum);
return (1);
}
@ -710,8 +710,6 @@ static int ascii_convert_house(struct char_data *ch, obj_vnum vnum)
}
}
fprintf(out, "$~\n");
fclose(in);
fclose(out);

View file

@ -22,6 +22,8 @@
#include "config.h"
#include "modify.h"
#include "genolc.h" /* for strip_cr and sprintascii */
#include "toml.h"
#include "toml_utils.h"
/* these factors should be unique integers */
#define CRYO_FACTOR 4
@ -37,106 +39,84 @@ static int Crash_load_objs(struct char_data *ch);
static int handle_obj(struct obj_data *obj, struct char_data *ch, int locate, struct obj_data **cont_rows);
static void Crash_write_header(struct char_data *ch, FILE *fp, int savecode);
static int toml_get_int_default(toml_table_t *tab, const char *key, int def)
{
toml_datum_t d = toml_int_in(tab, key);
if (!d.ok)
return def;
return (int)d.u.i;
}
static char *toml_get_string_dup(toml_table_t *tab, const char *key)
{
toml_datum_t d = toml_string_in(tab, key);
if (!d.ok)
return NULL;
return d.u.s;
}
static void toml_read_int_array(toml_array_t *arr, int *out, int out_count, int def)
{
int i;
for (i = 0; i < out_count; i++)
out[i] = def;
if (!arr)
return;
for (i = 0; i < out_count; i++) {
toml_datum_t d = toml_int_at(arr, i);
if (d.ok)
out[i] = (int)d.u.i;
}
}
/* Writes one object record to FILE. Old name: Obj_to_store().
* Updated to save all NUM_OBJ_VAL_POSITIONS values instead of only 4. */
int objsave_save_obj_record(struct obj_data *obj, FILE *fp, int locate)
{
int i;
char buf1[MAX_STRING_LENGTH + 1];
struct obj_data *temp = NULL;
int out_locate = (locate > 0) ? locate : 0;
int nest = (locate < 0) ? -locate : 0;
/* Build a prototype baseline to diff against so we only emit changed fields */
if (GET_OBJ_VNUM(obj) != NOTHING)
temp = read_object(GET_OBJ_VNUM(obj), VIRTUAL);
else {
temp = create_obj();
temp->item_number = NOWHERE;
fprintf(fp, "\n[[object]]\n");
fprintf(fp, "vnum = %d\n", GET_OBJ_VNUM(obj));
fprintf(fp, "locate = %d\n", out_locate);
fprintf(fp, "nest = %d\n", nest);
fprintf(fp, "values = [");
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
if (i > 0)
fputs(", ", fp);
fprintf(fp, "%d", GET_OBJ_VAL(obj, i));
}
fprintf(fp, "]\n");
if (obj->main_description) {
strcpy(buf1, obj->main_description);
fprintf(fp, "extra_flags = [%d, %d, %d, %d]\n",
GET_OBJ_EXTRA(obj)[0], GET_OBJ_EXTRA(obj)[1],
GET_OBJ_EXTRA(obj)[2], GET_OBJ_EXTRA(obj)[3]);
fprintf(fp, "wear_flags = [%d, %d, %d, %d]\n",
GET_OBJ_WEAR(obj)[0], GET_OBJ_WEAR(obj)[1],
GET_OBJ_WEAR(obj)[2], GET_OBJ_WEAR(obj)[3]);
toml_write_kv_string_opt(fp, "name", obj->name);
toml_write_kv_string_opt(fp, "short", obj->short_description);
toml_write_kv_string_opt(fp, "description", obj->description);
if (obj->main_description && *obj->main_description) {
strlcpy(buf1, obj->main_description, sizeof(buf1));
strip_cr(buf1);
} else
*buf1 = 0;
/* Header and placement */
fprintf(fp, "#%d\n", GET_OBJ_VNUM(obj));
/* Top-level worn slots are positive (1..NUM_WEARS); inventory is 0.
* Children use negative numbers from Crash_save recursion (,-1,-2,) we map that to Nest. */
if (locate > 0)
fprintf(fp, "Loc : %d\n", locate);
if (locate < 0) {
int nest = -locate; /* e.g. -1 => Nest:1, -2 => Nest:2, etc. */
fprintf(fp, "Nest: %d\n", nest);
} else {
fprintf(fp, "Nest: %d\n", 0); /* top-level object (inventory or worn) */
toml_write_kv_string(fp, "main_description", buf1);
}
/* Save all object values (diffed against proto) */
{
bool diff = FALSE;
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
if (GET_OBJ_VAL(obj, i) != GET_OBJ_VAL(temp, i)) {
diff = TRUE;
break;
}
}
if (diff) {
fprintf(fp, "Vals:");
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++)
fprintf(fp, " %d", GET_OBJ_VAL(obj, i));
fprintf(fp, "\n");
}
}
/* Extra flags (array words) */
if (GET_OBJ_EXTRA(obj) != GET_OBJ_EXTRA(temp))
fprintf(fp, "Flag: %d %d %d %d\n",
GET_OBJ_EXTRA(obj)[0], GET_OBJ_EXTRA(obj)[1],
GET_OBJ_EXTRA(obj)[2], GET_OBJ_EXTRA(obj)[3]);
/* Names/descriptions */
if (obj->name && (!temp->name || strcmp(obj->name, temp->name)))
fprintf(fp, "Name: %s\n", obj->name);
if (obj->short_description && (!temp->short_description ||
strcmp(obj->short_description, temp->short_description)))
fprintf(fp, "Shrt: %s\n", obj->short_description);
if (obj->description && (!temp->description ||
strcmp(obj->description, temp->description)))
fprintf(fp, "Desc: %s\n", obj->description);
if (obj->main_description && (!temp->main_description ||
strcmp(obj->main_description, temp->main_description)))
fprintf(fp, "ADes:\n%s~\n", buf1);
/* Core fields */
if (GET_OBJ_TYPE(obj) != GET_OBJ_TYPE(temp))
fprintf(fp, "Type: %d\n", GET_OBJ_TYPE(obj));
if (GET_OBJ_WEIGHT(obj) != GET_OBJ_WEIGHT(temp))
fprintf(fp, "Wght: %d\n", GET_OBJ_WEIGHT(obj));
if (GET_OBJ_COST(obj) != GET_OBJ_COST(temp))
fprintf(fp, "Cost: %d\n", GET_OBJ_COST(obj));
/* Permanent affects (array words) */
if (GET_OBJ_AFFECT(obj)[0] != GET_OBJ_AFFECT(temp)[0] ||
GET_OBJ_AFFECT(obj)[1] != GET_OBJ_AFFECT(temp)[1] ||
GET_OBJ_AFFECT(obj)[2] != GET_OBJ_AFFECT(temp)[2] ||
GET_OBJ_AFFECT(obj)[3] != GET_OBJ_AFFECT(temp)[3])
fprintf(fp, "Perm: %d %d %d %d\n",
GET_OBJ_AFFECT(obj)[0], GET_OBJ_AFFECT(obj)[1],
GET_OBJ_AFFECT(obj)[2], GET_OBJ_AFFECT(obj)[3]);
/* Wear flags (array words) */
if (GET_OBJ_WEAR(obj)[0] != GET_OBJ_WEAR(temp)[0] ||
GET_OBJ_WEAR(obj)[1] != GET_OBJ_WEAR(temp)[1] ||
GET_OBJ_WEAR(obj)[2] != GET_OBJ_WEAR(temp)[2] ||
GET_OBJ_WEAR(obj)[3] != GET_OBJ_WEAR(temp)[3])
fprintf(fp, "Wear: %d %d %d %d\n",
GET_OBJ_WEAR(obj)[0], GET_OBJ_WEAR(obj)[1],
GET_OBJ_WEAR(obj)[2], GET_OBJ_WEAR(obj)[3]);
/* (If you also persist applies, extra descs, scripts, etc., keep that code here unchanged) */
fprintf(fp, "type = %d\n", GET_OBJ_TYPE(obj));
fprintf(fp, "weight = %d\n", GET_OBJ_WEIGHT(obj));
fprintf(fp, "cost = %d\n", GET_OBJ_COST(obj));
return 1;
}
@ -266,10 +246,11 @@ int Crash_delete_file(char *name)
int Crash_delete_crashfile(struct char_data *ch)
{
char filename[MAX_INPUT_LENGTH];
int numread;
FILE *fl;
char errbuf[256];
toml_table_t *tab = NULL;
toml_table_t *header = NULL;
int savecode;
char line[READ_SIZE];
if (!get_filename(filename, sizeof(filename), CRASH_FILE, GET_NAME(ch)))
return FALSE;
@ -279,12 +260,19 @@ int Crash_delete_crashfile(struct char_data *ch)
log("SYSERR: checking for crash file %s (3): %s", filename, strerror(errno));
return FALSE;
}
numread = get_line(fl,line);
tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
fclose(fl);
if (numread == FALSE)
if (!tab)
return FALSE;
sscanf(line,"%d ",&savecode);
header = toml_table_in(tab, "header");
if (!header) {
toml_free(tab);
return FALSE;
}
savecode = toml_get_int_default(header, "save_code", SAVE_UNDEF);
toml_free(tab);
if (savecode == SAVE_CRASH)
Crash_delete_file(GET_NAME(ch));
@ -295,10 +283,11 @@ int Crash_delete_crashfile(struct char_data *ch)
int Crash_clean_file(char *name)
{
char filename[MAX_INPUT_LENGTH], filetype[20];
int numread;
FILE *fl;
int savecode, timed, netcost, coins, account, nitems;
char line[READ_SIZE];
char errbuf[256];
toml_table_t *tab = NULL;
toml_table_t *header = NULL;
int savecode, timed;
if (!get_filename(filename, sizeof(filename), CRASH_FILE, name))
return FALSE;
@ -310,13 +299,20 @@ int Crash_clean_file(char *name)
return FALSE;
}
numread = get_line(fl,line);
tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
fclose(fl);
if (numread == FALSE)
if (!tab)
return FALSE;
sscanf(line, "%d %d %d %d %d %d",&savecode,&timed,&netcost,
&coins,&account,&nitems);
header = toml_table_in(tab, "header");
if (!header) {
toml_free(tab);
return FALSE;
}
savecode = toml_get_int_default(header, "save_code", SAVE_UNDEF);
timed = toml_get_int_default(header, "timed", 0);
toml_free(tab);
if ((savecode == SAVE_CRASH) ||
(savecode == SAVE_LOGOUT) ||
@ -403,7 +399,13 @@ static void Crash_write_header(struct char_data *ch, FILE *fp, int savecode)
int account = ch ? GET_BANK_COINS(ch) : 0;
int nitems = 0;
fprintf(fp, "%d %d %d %d %d %d\n", savecode, timed, netcost, coins, account, nitems);
fprintf(fp, "[header]\n");
fprintf(fp, "save_code = %d\n", savecode);
fprintf(fp, "timed = %d\n", timed);
fprintf(fp, "net_cost = %d\n", netcost);
fprintf(fp, "coins = %d\n", coins);
fprintf(fp, "account = %d\n", account);
fprintf(fp, "item_count = %d\n", nitems);
}
void Crash_crashsave(struct char_data *ch)
@ -438,7 +440,6 @@ void Crash_crashsave(struct char_data *ch)
}
Crash_restore_weight(ch->carrying);
fprintf(fp, "$~\n");
fclose(fp);
REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_CRASH);
}
@ -476,7 +477,6 @@ void Crash_idlesave(struct char_data *ch)
}
Crash_restore_weight(ch->carrying);
fprintf(fp, "$~\n");
fclose(fp);
REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_CRASH);
}
@ -514,7 +514,6 @@ void Crash_rentsave(struct char_data *ch, int cost)
}
Crash_restore_weight(ch->carrying);
fprintf(fp, "$~\n");
fclose(fp);
REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_CRASH);
}
@ -553,100 +552,32 @@ void Crash_save_all(void)
}
}
/* Load all objects from file into memory. Updated to load NUM_OBJ_VAL_POSITIONS values. */
obj_save_data *objsave_parse_objects(FILE *fl)
/* Load all objects from TOML into memory. */
static obj_save_data *objsave_parse_objects_from_toml(toml_table_t *tab, const char *filename)
{
char line[MAX_STRING_LENGTH];
obj_save_data *head = NULL, *tail = NULL;
toml_array_t *arr = NULL;
int count, i;
/* State for the object were currently assembling */
struct obj_data *temp = NULL;
int pending_locate = 0; /* 0 = inventory, 1..NUM_WEARS = worn slot */
int pending_nest = 0; /* 0 = top-level; >0 = inside container at level-1 */
arr = toml_array_in(tab, "object");
if (!arr)
return NULL;
/* --- helpers (GCC nested functions OK in tbaMUD build) ---------------- */
count = toml_array_nelem(arr);
for (i = 0; i < count; i++) {
toml_table_t *obj_tab = toml_table_at(arr, i);
struct obj_data *temp = NULL;
int locate, nest;
int values[NUM_OBJ_VAL_POSITIONS];
int flags[4];
char *str = NULL;
/* append current object to the result list with proper locate */
void commit_current(void) {
if (!temp) return;
if (!obj_tab)
continue;
if (GET_OBJ_TYPE(temp) == ITEM_MONEY)
update_money_obj(temp);
/* sanitize top-level locate range only; children will be negative later */
int loc = pending_locate;
if (pending_nest <= 0) {
if (loc < 0 || loc > NUM_WEARS) {
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: bad locate %d for vnum %d; defaulting to inventory.",
loc, GET_OBJ_VNUM(temp));
loc = 0;
}
}
/* convert Nest>0 into negative locate for handle_obj()/cont_row */
int effective_loc = (pending_nest > 0) ? -pending_nest : loc;
obj_save_data *node = NULL;
CREATE(node, obj_save_data, 1);
node->obj = temp;
node->locate = effective_loc;
node->next = NULL;
if (!head) head = node, tail = node;
else tail->next = node, tail = node;
temp = NULL;
pending_locate = 0;
pending_nest = 0;
}
/* split a line into normalized tag (no colon) and payload pointer */
void split_tag_line(const char *src, char tag_out[6], const char **payload_out) {
const char *s = src;
while (*s && isspace((unsigned char)*s)) s++; /* skip leading ws */
const char *te = s;
while (*te && !isspace((unsigned char)*te) && *te != ':') te++;
size_t tlen = (size_t)(te - s);
if (tlen > 5) tlen = 5;
memcpy(tag_out, s, tlen);
tag_out[tlen] = '\0';
const char *p = te;
while (*p && isspace((unsigned char)*p)) p++;
if (*p == ':') {
p++;
while (*p && isspace((unsigned char)*p)) p++;
}
*payload_out = p;
}
/* ---------------------------------------------------------------------- */
while (get_line(fl, line)) {
if (!*line) continue;
/* New object header: "#<vnum>" (commit any previous one first) */
if (*line == '#') {
if (temp) commit_current();
long vnum = -1L;
vnum = strtol(line + 1, NULL, 10);
if (vnum <= 0 && vnum != -1L) {
mudlog(NRM, LVL_IMMORT, TRUE, "SAVE-LOAD: bad vnum header: '%s'", line);
temp = NULL;
pending_locate = 0;
pending_nest = 0;
continue;
}
/* Instantiate from prototype if available, else create a blank */
if (vnum == -1L) {
{
int vnum = toml_get_int_default(obj_tab, "vnum", -1);
if (vnum == -1) {
temp = create_obj();
temp->item_number = NOTHING;
if (!temp->name) temp->name = strdup("object");
@ -658,133 +589,122 @@ obj_save_data *objsave_parse_objects(FILE *fl)
temp = read_object(rnum, REAL);
} else {
temp = create_obj();
/* Do NOT assign GET_OBJ_VNUM(temp); item_number derives vnum. */
if (!temp->name) temp->name = strdup("object");
if (!temp->short_description) temp->short_description = strdup("an object");
if (!temp->description) temp->description = strdup("An object lies here.");
}
}
pending_locate = 0;
pending_nest = 0;
continue;
}
/* Normal data line: TAG [ : ] payload */
char tag[6];
const char *payload = NULL;
split_tag_line(line, tag, &payload);
locate = toml_get_int_default(obj_tab, "locate", 0);
if (locate < 0 || locate > NUM_WEARS)
locate = 0;
if (!*tag) continue;
if (!temp) {
mudlog(NRM, LVL_IMMORT, TRUE, "SAVE-LOAD: data before header ignored: '%s'", line);
continue;
}
if (!strcmp(tag, "Loc")) {
pending_locate = (int)strtol(payload, NULL, 10);
}
else if (!strcmp(tag, "Nest")) {
pending_nest = (int)strtol(payload, NULL, 10);
if (pending_nest < 0) pending_nest = 0;
if (pending_nest > MAX_BAG_ROWS) {
nest = toml_get_int_default(obj_tab, "nest", 0);
if (nest < 0)
nest = 0;
if (nest > MAX_BAG_ROWS) {
if (filename)
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: nest level %d too deep in %s; clamping to %d.",
nest, filename, MAX_BAG_ROWS);
else
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: nest level %d too deep; clamping to %d.",
pending_nest, MAX_BAG_ROWS);
pending_nest = MAX_BAG_ROWS;
}
nest, MAX_BAG_ROWS);
nest = MAX_BAG_ROWS;
}
else if (!strcmp(tag, "Vals")) {
const char *p = payload;
for (int i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
if (!*p) { GET_OBJ_VAL(temp, i) = 0; continue; }
GET_OBJ_VAL(temp, i) = (int)strtol(p, (char **)&p, 10);
}
}
else if (!strcmp(tag, "Wght")) {
GET_OBJ_WEIGHT(temp) = (int)strtol(payload, NULL, 10);
}
else if (!strcmp(tag, "Cost")) {
GET_OBJ_COST(temp) = (int)strtol(payload, NULL, 10);
}
else if (!strcmp(tag, "Rent")) {
/* Legacy tag ignored (cost-per-day no longer used). */
}
else if (!strcmp(tag, "Type")) {
GET_OBJ_TYPE(temp) = (int)strtol(payload, NULL, 10);
}
else if (!strcmp(tag, "Wear")) {
unsigned long words[4] = {0,0,0,0};
const char *p = payload;
for (int i = 0; i < 4 && *p; i++) words[i] = strtoul(p, (char **)&p, 10);
#if defined(TW_ARRAY_MAX) && defined(GET_OBJ_WEAR_AR)
for (int i = 0; i < 4; i++) {
if (i < TW_ARRAY_MAX) GET_OBJ_WEAR_AR(temp, i) = (bitvector_t)words[i];
else if (words[i])
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: Wear word %d (%lu) truncated (TW_ARRAY_MAX=%d).",
i, words[i], TW_ARRAY_MAX);
}
#elif defined(GET_OBJ_WEAR_AR)
for (int i = 0; i < 4; i++) GET_OBJ_WEAR_AR(temp, i) = (bitvector_t)words[i];
#endif
}
else if (!strcmp(tag, "Flag")) {
unsigned long words[4] = {0,0,0,0};
const char *p = payload;
for (int i = 0; i < 4 && *p; i++) words[i] = strtoul(p, (char **)&p, 10);
toml_read_int_array(toml_array_in(obj_tab, "values"), values, NUM_OBJ_VAL_POSITIONS, 0);
for (int j = 0; j < NUM_OBJ_VAL_POSITIONS; j++)
GET_OBJ_VAL(temp, j) = values[j];
#if defined(EF_ARRAY_MAX) && defined(GET_OBJ_EXTRA_AR)
for (int i = 0; i < 4; i++) {
if (i < EF_ARRAY_MAX) GET_OBJ_EXTRA_AR(temp, i) = (bitvector_t)words[i];
else if (words[i])
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: Extra word %d (%lu) truncated (EF_ARRAY_MAX=%d).",
i, words[i], EF_ARRAY_MAX);
}
#elif defined(GET_OBJ_EXTRA_AR)
for (int i = 0; i < 4; i++) GET_OBJ_EXTRA_AR(temp, i) = (bitvector_t)words[i];
#endif
toml_read_int_array(toml_array_in(obj_tab, "extra_flags"), flags, 4, 0);
for (int j = 0; j < 4; j++)
GET_OBJ_EXTRA(temp)[j] = flags[j];
toml_read_int_array(toml_array_in(obj_tab, "wear_flags"), flags, 4, 0);
for (int j = 0; j < 4; j++)
GET_OBJ_WEAR(temp)[j] = flags[j];
str = toml_get_string_dup(obj_tab, "name");
if (str) {
if (temp->name)
free(temp->name);
temp->name = str;
}
else if (!strcmp(tag, "Name")) {
if (temp->name) free(temp->name);
temp->name = *payload ? strdup(payload) : strdup("object");
str = toml_get_string_dup(obj_tab, "short");
if (str) {
if (temp->short_description)
free(temp->short_description);
temp->short_description = str;
}
else if (!strcmp(tag, "Shrt")) {
if (temp->short_description) free(temp->short_description);
temp->short_description = *payload ? strdup(payload) : strdup("an object");
str = toml_get_string_dup(obj_tab, "description");
if (str) {
if (temp->description)
free(temp->description);
temp->description = str;
}
else if (!strcmp(tag, "Desc")) {
if (temp->description) free(temp->description);
temp->description = *payload ? strdup(payload) : strdup("An object lies here.");
str = toml_get_string_dup(obj_tab, "main_description");
if (str) {
if (temp->main_description)
free(temp->main_description);
temp->main_description = str;
}
else if (!strcmp(tag, "ADes")) {
if (temp->main_description) free(temp->main_description);
temp->main_description = *payload ? strdup(payload) : NULL;
}
else if (!strcmp(tag, "End")) {
commit_current();
}
else {
mudlog(NRM, LVL_IMMORT, TRUE, "SAVE-LOAD: unknown tag '%s'", tag);
GET_OBJ_TYPE(temp) = toml_get_int_default(obj_tab, "type", GET_OBJ_TYPE(temp));
GET_OBJ_WEIGHT(temp) = toml_get_int_default(obj_tab, "weight", GET_OBJ_WEIGHT(temp));
GET_OBJ_COST(temp) = toml_get_int_default(obj_tab, "cost", GET_OBJ_COST(temp));
if (GET_OBJ_TYPE(temp) == ITEM_MONEY)
update_money_obj(temp);
{
int effective_loc = (nest > 0) ? -nest : locate;
obj_save_data *node = NULL;
CREATE(node, obj_save_data, 1);
node->obj = temp;
node->locate = effective_loc;
node->next = NULL;
if (!head)
head = node, tail = node;
else
tail->next = node, tail = node;
}
}
if (temp) commit_current();
return head;
}
obj_save_data *objsave_parse_objects(FILE *fl)
{
char errbuf[256];
toml_table_t *tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
obj_save_data *list = NULL;
if (!tab)
return NULL;
list = objsave_parse_objects_from_toml(tab, NULL);
toml_free(tab);
return list;
}
static int Crash_load_objs(struct char_data *ch) {
FILE *fl;
char filename[PATH_MAX];
char line[READ_SIZE];
char buf[MAX_STRING_LENGTH];
int i, orig_save_code, num_objs=0;
struct obj_data *cont_row[MAX_BAG_ROWS];
int savecode = SAVE_UNDEF;
int timed=0,netcost=0,coins,account,nitems;
int timed=0,netcost=0,coins=0,account=0,nitems=0;
char errbuf[256];
toml_table_t *tab = NULL;
toml_table_t *header = NULL;
obj_save_data *loaded, *current;
if (!get_filename(filename, sizeof(filename), CRASH_FILE, GET_NAME(ch)))
@ -810,10 +730,28 @@ static int Crash_load_objs(struct char_data *ch) {
return 1;
}
if (!get_line(fl, line))
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "Failed to read player's save code: %s.", GET_NAME(ch));
else
sscanf(line,"%d %d %d %d %d %d",&savecode, &timed, &netcost,&coins,&account,&nitems);
tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
fclose(fl);
if (!tab) {
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE,
"Failed to parse player's object file %s: %s.", filename, errbuf);
return 1;
}
header = toml_table_in(tab, "header");
if (!header) {
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE,
"Player object file %s missing header.", filename);
toml_free(tab);
return 1;
}
savecode = toml_get_int_default(header, "save_code", SAVE_UNDEF);
timed = toml_get_int_default(header, "timed", 0);
netcost = toml_get_int_default(header, "net_cost", 0);
coins = toml_get_int_default(header, "coins", 0);
account = toml_get_int_default(header, "account", 0);
nitems = toml_get_int_default(header, "item_count", 0);
if (savecode == SAVE_LOGOUT || savecode == SAVE_TIMEDOUT) {
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE,
@ -844,7 +782,8 @@ static int Crash_load_objs(struct char_data *ch) {
break;
}
loaded = objsave_parse_objects(fl);
loaded = objsave_parse_objects_from_toml(tab, filename);
toml_free(tab);
for (current = loaded; current != NULL; current=current->next)
num_objs += handle_obj(current->obj, ch, current->locate, cont_row);
@ -874,8 +813,6 @@ static int Crash_load_objs(struct char_data *ch) {
mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "%s (level %d) has %d object%s.",
GET_NAME(ch), GET_LEVEL(ch), num_objs, num_objs != 1 ? "s" : "");
fclose(fl);
if ((orig_save_code == SAVE_LOGOUT) || (orig_save_code == SAVE_CRYO))
return 0;
else

File diff suppressed because it is too large Load diff

1346
src/set.c

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,17 @@
#include "modify.h"
#include "spells.h" /* for skill_name() */
#include "screen.h"
#include "toml.h"
static char *toml_get_string_dup(toml_table_t *tab, const char *key)
{
toml_datum_t d = toml_string_in(tab, key);
if (!d.ok)
return NULL;
return d.u.s;
}
/* Global variables definitions used externally */
/* Constant list for printing out who we sell to */
@ -57,9 +68,11 @@ static int top(struct stack_data *stack); /**< @todo Move to utils.c */
static int pop(struct stack_data *stack); /**< @todo Move to utils.c */
static char *list_object(struct obj_data *obj, int cnt, int oindex, int shop_nr, struct char_data *keeper, struct char_data *seller);
static void sort_keeper_objs(struct char_data *keeper, int shop_nr);
#if 0
static char *read_shop_message(int mnum, room_vnum shr, FILE *shop_f, const char *why);
static int read_type_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max);
static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max, int type);
#endif
static void shopping_list(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
static void shopping_value(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
static void shopping_sell(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
@ -78,6 +91,22 @@ static int is_ok(struct char_data *keeper, struct char_data *ch, int shop_nr);
static void evaluate_operation(struct stack_data *ops, struct stack_data *vals);
static int find_oper_num(char token);
static int evaluate_expression(struct obj_data *obj, char *expr);
static float toml_get_float_default(toml_table_t *tab, const char *key, float def)
{
toml_datum_t v = toml_double_in(tab, key);
if (!v.ok)
return def;
return (float)v.u.d;
}
static int toml_get_int_default(toml_table_t *tab, const char *key, int def)
{
toml_datum_t v = toml_int_in(tab, key);
if (!v.ok)
return def;
return (int)v.u.i;
}
static int trade_with(struct obj_data *item, int shop_nr);
static int same_obj(struct obj_data *obj1, struct obj_data *obj2);
static int shop_producing(struct obj_data *item, int shop_nr);
@ -86,9 +115,11 @@ static char *times_message(struct obj_data *obj, char *name, int num);
static int buy_price(struct obj_data *obj, int shop_nr, struct char_data *keeper, struct char_data *buyer);
static int sell_price(struct obj_data *obj, int shop_nr, struct char_data *keeper, struct char_data *seller);
static int ok_shop_room(int shop_nr, room_vnum room);
#if 0
static int add_to_shop_list(struct shop_buy_data *list, int type, int *len, int *val);
static int end_read_list(struct shop_buy_data *list, int len, int error);
static void read_line(FILE *shop_f, const char *string, void *data);
#endif
/* Local file scope only variables */
static int cmd_say;
@ -1104,6 +1135,7 @@ int ok_damage_shopkeeper(struct char_data *ch, struct char_data *victim)
}
/* val == obj_vnum and obj_rnum (?) */
#if 0
static int add_to_shop_list(struct shop_buy_data *list, int type, int *len, int *val)
{
if (*val != NOTHING && *val >= 0) { /* necessary after changing to unsigned v/rnums -- Welcor */
@ -1140,7 +1172,9 @@ static void read_line(FILE *shop_f, const char *string, void *data)
exit(1);
}
}
#endif
#if 0
static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format,
int max, int type)
{
@ -1160,7 +1194,9 @@ static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format,
}
return (end_read_list(list, len, error));
}
#endif
#if 0
/* END_OF inefficient. */
static int read_type_list(FILE *shop_f, struct shop_buy_data *list,
int new_format, int max)
@ -1251,76 +1287,172 @@ static char *read_shop_message(int mnum, room_vnum shr, FILE *shop_f, const char
}
return (tbuf);
}
#endif
static char *dup_shop_message(int mnum, room_vnum shr, const char *msg)
{
int cht, ss = 0, ds = 0, err = 0;
char *tbuf;
if (!msg || !*msg)
return NULL;
tbuf = strdup(msg);
for (cht = 0; tbuf[cht]; cht++) {
if (tbuf[cht] != '%')
continue;
if (tbuf[cht + 1] == 's')
ss++;
else if (tbuf[cht + 1] == 'd' && (mnum == 5 || mnum == 6)) {
if (ss == 0) {
log("SYSERR: Shop #%d has %%d before %%s, message #%d.", shr, mnum);
err++;
}
ds++;
} else if (tbuf[cht + 1] != '%') {
log("SYSERR: Shop #%d has invalid format '%%%c' in message #%d.", shr, tbuf[cht + 1], mnum);
err++;
}
}
if (ss > 1 || ds > 1) {
log("SYSERR: Shop #%d has too many specifiers for message #%d. %%s=%d %%d=%d", shr, mnum, ss, ds);
err++;
}
if (err) {
free(tbuf);
return NULL;
}
return (tbuf);
}
void boot_the_shops(FILE *shop_f, char *filename, int rec_count)
{
char *buf, buf2[256];
int temp, count, new_format = FALSE;
struct shop_buy_data list[MAX_SHOP_OBJ + 1];
int done = FALSE;
FILE *fp;
toml_table_t *tab;
toml_array_t *shops;
char errbuf[200];
int i;
snprintf(buf2, sizeof(buf2), "beginning of shop file %s", filename);
(void)shop_f;
while (!done) {
buf = fread_string(shop_f, buf2);
if (*buf == '#') { /* New shop */
sscanf(buf, "#%d\n", &temp);
snprintf(buf2, sizeof(buf2), "shop #%d in shop file %s", temp, filename);
free(buf); /* Plug memory leak! */
top_shop++;
if (!top_shop)
CREATE(shop_index, struct shop_data, rec_count);
SHOP_NUM(top_shop) = temp;
temp = read_list(shop_f, list, new_format, MAX_PROD, LIST_PRODUCE);
CREATE(shop_index[top_shop].producing, obj_vnum, temp);
for (count = 0; count < temp; count++)
SHOP_PRODUCT(top_shop, count) = BUY_TYPE(list[count]);
read_line(shop_f, "%f", &SHOP_BUYPROFIT(top_shop));
read_line(shop_f, "%f", &SHOP_SELLPROFIT(top_shop));
temp = read_type_list(shop_f, list, new_format, MAX_TRADE);
CREATE(shop_index[top_shop].type, struct shop_buy_data, temp);
for (count = 0; count < temp; count++) {
SHOP_BUYTYPE(top_shop, count) = BUY_TYPE(list[count]);
SHOP_BUYWORD(top_shop, count) = BUY_WORD(list[count]);
}
shop_index[top_shop].no_such_item1 = read_shop_message(0, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].no_such_item2 = read_shop_message(1, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].do_not_buy = read_shop_message(2, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].missing_cash1 = read_shop_message(3, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].missing_cash2 = read_shop_message(4, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].message_buy = read_shop_message(5, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].message_sell = read_shop_message(6, SHOP_NUM(top_shop), shop_f, buf2);
read_line(shop_f, "%d", &SHOP_BROKE_TEMPER(top_shop));
read_line(shop_f, "%ld", &SHOP_BITVECTOR(top_shop));
read_line(shop_f, "%d", &SHOP_KEEPER(top_shop));
SHOP_KEEPER(top_shop) = real_mobile(SHOP_KEEPER(top_shop));
read_line(shop_f, "%d", &SHOP_TRADE_WITH(top_shop));
temp = read_list(shop_f, list, new_format, 1, LIST_ROOM);
CREATE(shop_index[top_shop].in_room, room_vnum, temp);
for (count = 0; count < temp; count++)
SHOP_ROOM(top_shop, count) = BUY_TYPE(list[count]);
read_line(shop_f, "%d", &SHOP_OPEN1(top_shop));
read_line(shop_f, "%d", &SHOP_CLOSE1(top_shop));
read_line(shop_f, "%d", &SHOP_OPEN2(top_shop));
read_line(shop_f, "%d", &SHOP_CLOSE2(top_shop));
SHOP_BANK(top_shop) = 0;
SHOP_SORT(top_shop) = 0;
SHOP_FUNC(top_shop) = NULL;
} else {
if (*buf == '$') /* EOF */
done = TRUE;
else if (strstr(buf, VERSION3_TAG)) /* New format marker */
new_format = TRUE;
free(buf); /* Plug memory leak! */
}
fp = fopen(filename, "r");
if (!fp) {
log("SYSERR: %s: %s", filename, strerror(errno));
exit(1);
}
tab = toml_parse_file(fp, errbuf, sizeof(errbuf));
fclose(fp);
if (!tab) {
log("SYSERR: parsing file '%s': %s", filename, errbuf);
exit(1);
}
shops = toml_array_in(tab, "shop");
if (!shops) {
toml_free(tab);
log("SYSERR: TOML file '%s' missing 'shop' array.", filename);
exit(1);
}
for (i = 0; i < toml_array_nelem(shops); i++) {
toml_table_t *shop_tab = toml_table_at(shops, i);
toml_array_t *arr;
toml_table_t *msgs;
int count, temp;
if (!shop_tab)
continue;
top_shop++;
if (!top_shop)
CREATE(shop_index, struct shop_data, rec_count);
SHOP_NUM(top_shop) = toml_get_int_default(shop_tab, "vnum", 0);
arr = toml_array_in(shop_tab, "products");
temp = arr ? toml_array_nelem(arr) : 0;
CREATE(shop_index[top_shop].producing, obj_vnum, temp + 1);
for (count = 0; count < temp; count++) {
toml_datum_t v = toml_int_at(arr, count);
SHOP_PRODUCT(top_shop, count) = v.ok ? (obj_vnum)v.u.i : NOTHING;
}
SHOP_PRODUCT(top_shop, temp) = NOTHING;
SHOP_BUYPROFIT(top_shop) = toml_get_float_default(shop_tab, "buy_profit", 0.0f);
SHOP_SELLPROFIT(top_shop) = toml_get_float_default(shop_tab, "sell_profit", 0.0f);
arr = toml_array_in(shop_tab, "buy_type");
temp = arr ? toml_array_nelem(arr) : 0;
CREATE(shop_index[top_shop].type, struct shop_buy_data, temp + 1);
for (count = 0; count < temp; count++) {
toml_table_t *bt_tab = toml_table_at(arr, count);
int t = NOTHING;
char *word = NULL;
if (bt_tab) {
t = toml_get_int_default(bt_tab, "type", NOTHING);
word = toml_get_string_dup(bt_tab, "keyword");
}
SHOP_BUYTYPE(top_shop, count) = t;
SHOP_BUYWORD(top_shop, count) = word;
}
SHOP_BUYTYPE(top_shop, temp) = NOTHING;
SHOP_BUYWORD(top_shop, temp) = NULL;
msgs = toml_table_in(shop_tab, "messages");
if (msgs) {
char *msg;
msg = toml_get_string_dup(msgs, "no_such_item1");
shop_index[top_shop].no_such_item1 = dup_shop_message(0, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "no_such_item2");
shop_index[top_shop].no_such_item2 = dup_shop_message(1, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "do_not_buy");
shop_index[top_shop].do_not_buy = dup_shop_message(2, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "missing_cash1");
shop_index[top_shop].missing_cash1 = dup_shop_message(3, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "missing_cash2");
shop_index[top_shop].missing_cash2 = dup_shop_message(4, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "message_buy");
shop_index[top_shop].message_buy = dup_shop_message(5, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "message_sell");
shop_index[top_shop].message_sell = dup_shop_message(6, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
}
SHOP_BROKE_TEMPER(top_shop) = toml_get_int_default(shop_tab, "broke_temper", 0);
SHOP_BITVECTOR(top_shop) = (long)toml_get_int_default(shop_tab, "bitvector", 0);
SHOP_KEEPER(top_shop) = toml_get_int_default(shop_tab, "keeper", NOBODY);
SHOP_KEEPER(top_shop) = real_mobile(SHOP_KEEPER(top_shop));
SHOP_TRADE_WITH(top_shop) = toml_get_int_default(shop_tab, "trade_with", 0);
arr = toml_array_in(shop_tab, "rooms");
temp = arr ? toml_array_nelem(arr) : 0;
CREATE(shop_index[top_shop].in_room, room_vnum, temp + 1);
for (count = 0; count < temp; count++) {
toml_datum_t v = toml_int_at(arr, count);
SHOP_ROOM(top_shop, count) = v.ok ? (room_vnum)v.u.i : NOWHERE;
}
SHOP_ROOM(top_shop, temp) = NOWHERE;
SHOP_OPEN1(top_shop) = toml_get_int_default(shop_tab, "open1", 0);
SHOP_CLOSE1(top_shop) = toml_get_int_default(shop_tab, "close1", 0);
SHOP_OPEN2(top_shop) = toml_get_int_default(shop_tab, "open2", 0);
SHOP_CLOSE2(top_shop) = toml_get_int_default(shop_tab, "close2", 0);
SHOP_BANK(top_shop) = toml_get_int_default(shop_tab, "bank", 0);
SHOP_SORT(top_shop) = toml_get_int_default(shop_tab, "sort", 0);
SHOP_FUNC(top_shop) = NULL;
}
toml_free(tab);
}
void assign_the_shopkeepers(void)

58
src/toml_utils.c Normal file
View file

@ -0,0 +1,58 @@
#include "conf.h"
#include "sysdep.h"
#include "toml_utils.h"
static void toml_write_escaped(FILE *fp, const char *value)
{
const unsigned char *p = (const unsigned char *)value;
while (p && *p) {
switch (*p) {
case '\\':
fputs("\\\\", fp);
break;
case '"':
fputs("\\\"", fp);
break;
case '\n':
fputs("\\n", fp);
break;
case '\r':
fputs("\\r", fp);
break;
case '\t':
fputs("\\t", fp);
break;
default:
if (*p < 0x20) {
fprintf(fp, "\\u%04x", (unsigned int)*p);
} else {
fputc(*p, fp);
}
break;
}
p++;
}
}
void toml_write_string(FILE *fp, const char *value)
{
fputc('"', fp);
if (value && *value)
toml_write_escaped(fp, value);
fputc('"', fp);
}
void toml_write_kv_string(FILE *fp, const char *key, const char *value)
{
fprintf(fp, "%s = ", key);
toml_write_string(fp, value);
fputc('\n', fp);
}
void toml_write_kv_string_opt(FILE *fp, const char *key, const char *value)
{
if (!value || !*value)
return;
toml_write_kv_string(fp, key, value);
}

10
src/toml_utils.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef TOML_UTILS_H
#define TOML_UTILS_H
#include <stdio.h>
void toml_write_string(FILE *fp, const char *value);
void toml_write_kv_string(FILE *fp, const char *key, const char *value);
void toml_write_kv_string_opt(FILE *fp, const char *key, const char *value);
#endif

14
third_party/tomlc99/.editorconfig vendored Normal file
View file

@ -0,0 +1,14 @@
root = true
[*]
end_of_line = lf
insert_final_newline = false
trim_trailing_whitespace = true
[*.{c,h}]
indent_style = space
indent_size = 2
[Makefile]
indent_style = tab
indent_size = 4

38
third_party/tomlc99/.gitignore vendored Normal file
View file

@ -0,0 +1,38 @@
*~
# Object files
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
toml_cat
toml_json
toml_sample
# Debug files
*.dSYM/
*.su

22
third_party/tomlc99/LICENSE vendored Normal file
View file

@ -0,0 +1,22 @@
MIT License
Copyright (c) CK Tan
https://github.com/cktan/tomlc99
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

53
third_party/tomlc99/Makefile vendored Normal file
View file

@ -0,0 +1,53 @@
prefix ?= /usr/local
HFILES = toml.h
CFILES = toml.c
OBJ = $(CFILES:.c=.o)
EXEC = toml_json toml_cat toml_sample
PCFILE = libtoml.pc
CFLAGS = -std=c99 -Wall -Wextra -fpic
LIB_VERSION = 1.0
LIB = libtoml.a
LIB_SHARED = libtoml.so.$(LIB_VERSION)
# to compile for debug: make DEBUG=1
# to compile for no debug: make
ifdef DEBUG
CFLAGS += -O0 -g
else
CFLAGS += -O2 -DNDEBUG
endif
all: $(LIB) $(LIB_SHARED) $(EXEC)
*.o: $(HFILES)
libtoml.a: toml.o
ar -rcs $@ $^
libtoml.so.$(LIB_VERSION): toml.o
$(CC) -shared -o $@ $^
$(EXEC): $(LIB)
install: all
install -d ${prefix}/include ${prefix}/lib
install toml.h ${prefix}/include
install $(LIB) ${prefix}/lib
install $(LIB_SHARED) ${prefix}/lib
ifeq "$(prefix)" "/usr/local"
ifneq ("$(wildcard $(PCFILE))","")
install $(PCFILE) /usr/local/lib/pkgconfig
endif
endif
clean:
rm -f *.o $(EXEC) $(LIB) $(LIB_SHARED)
format:
clang-format -i $(shell find . -name '*.[ch]')
.PHONY: all clean install format

198
third_party/tomlc99/README.md vendored Normal file
View file

@ -0,0 +1,198 @@
# tomlc99
>
> **Note: OBSOLETED. There is a newer version of this library available at [tomlc17](https://github.com/cktan/tomlc17), which is compatible with c99.**
>
TOML in c99; v1.0 compliant.
If you are looking for a C++ library, you might try this wrapper: [https://github.com/cktan/tomlcpp](https://github.com/cktan/tomlcpp).
* Compatible with [TOML v1.0.0](https://toml.io/en/v1.0.0).
* Tested with multiple test suites, including
[toml-lang/toml-test](https://github.com/toml-lang/toml-test) and
[iarna/toml-spec-tests](https://github.com/iarna/toml-spec-tests).
* Provides very simple and intuitive interface.
## Usage
Please see the `toml.h` file for details. The following is a simple example that
parses this config file:
```toml
[server]
host = "www.example.com"
port = [ 8080, 8181, 8282 ]
```
These are the usual steps for getting values from a file:
1. Parse the TOML file.
2. Traverse and locate a table in TOML.
3. Extract values from the table.
4. Free up allocated memory.
Below is an example of parsing the values from the example table.
```c
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "toml.h"
static void error(const char* msg, const char* msg1)
{
fprintf(stderr, "ERROR: %s%s\n", msg, msg1?msg1:"");
exit(1);
}
int main()
{
FILE* fp;
char errbuf[200];
// 1. Read and parse toml file
fp = fopen("sample.toml", "r");
if (!fp) {
error("cannot open sample.toml - ", strerror(errno));
}
toml_table_t* conf = toml_parse_file(fp, errbuf, sizeof(errbuf));
fclose(fp);
if (!conf) {
error("cannot parse - ", errbuf);
}
// 2. Traverse to a table.
toml_table_t* server = toml_table_in(conf, "server");
if (!server) {
error("missing [server]", "");
}
// 3. Extract values
toml_datum_t host = toml_string_in(server, "host");
if (!host.ok) {
error("cannot read server.host", "");
}
toml_array_t* portarray = toml_array_in(server, "port");
if (!portarray) {
error("cannot read server.port", "");
}
printf("host: %s\n", host.u.s);
printf("port: ");
for (int i = 0; ; i++) {
toml_datum_t port = toml_int_at(portarray, i);
if (!port.ok) break;
printf("%d ", (int)port.u.i);
}
printf("\n");
// 4. Free memory
free(host.u.s);
toml_free(conf);
return 0;
}
```
#### Accessing Table Content
TOML tables are dictionaries where lookups are done using string keys. In
general, all access functions on tables are named `toml_*_in(...)`.
In the normal case, you know the key and its content type, and retrievals can be done
using one of these functions:
```c
toml_string_in(tab, key);
toml_bool_in(tab, key);
toml_int_in(tab, key);
toml_double_in(tab, key);
toml_timestamp_in(tab, key);
toml_table_in(tab, key);
toml_array_in(tab, key);
```
You can also interrogate the keys in a table using an integer index:
```c
toml_table_t* tab = toml_parse_file(...);
for (int i = 0; ; i++) {
const char* key = toml_key_in(tab, i);
if (!key) break;
printf("key %d: %s\n", i, key);
}
```
#### Accessing Array Content
TOML arrays can be deref-ed using integer indices. In general, all access methods on arrays are named `toml_*_at()`.
To obtain the size of an array:
```c
int size = toml_array_nelem(arr);
```
To obtain the content of an array, use a valid index and call one of these functions:
```c
toml_string_at(arr, idx);
toml_bool_at(arr, idx);
toml_int_at(arr, idx);
toml_double_at(arr, idx);
toml_timestamp_at(arr, idx);
toml_table_at(arr, idx);
toml_array_at(arr, idx);
```
#### toml_datum_t
Some `toml_*_at` and `toml_*_in` functions return a toml_datum_t
structure. The `ok` flag in the structure indicates if the function
call was successful. If so, you may proceed to read the value
corresponding to the type of the content.
For example:
```
toml_datum_t host = toml_string_in(tab, "host");
if (host.ok) {
printf("host: %s\n", host.u.s);
free(host.u.s); /* FREE applies to string and timestamp types only */
}
```
** IMPORTANT: if the accessed value is a string or a timestamp, you must call `free(datum.u.s)` or `free(datum.u.ts)` respectively after usage. **
## Building and installing
A normal *make* suffices. You can also simply include the
`toml.c` and `toml.h` files in your project.
Invoking `make install` will install the header and library files into
/usr/local/{include,lib}.
Alternatively, specify `make install prefix=/a/file/path` to install into
/a/file/path/{include,lib}.
## Testing
To test against the standard test set provided by toml-lang/toml-test:
```sh
% make
% cd test1
% bash build.sh # do this once
% bash run.sh # this will run the test suite
```
To test against the standard test set provided by iarna/toml:
```sh
% make
% cd test2
% bash build.sh # do this once
% bash run.sh # this will run the test suite
```

11
third_party/tomlc99/libtoml.pc.sample vendored Normal file
View file

@ -0,0 +1,11 @@
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libtoml
URL: https://github.com/cktan/tomlc99/
Description: TOML C library in c99.
Version: v1.0
Libs: -L${libdir} -ltoml
Cflags: -I${includedir}

3
third_party/tomlc99/sample.toml vendored Normal file
View file

@ -0,0 +1,3 @@
[server]
host = "example.com"
port = [ 8080, 8181, 8282 ]

1
third_party/tomlc99/stdex/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/*.out

15
third_party/tomlc99/stdex/RUN.sh vendored Normal file
View file

@ -0,0 +1,15 @@
rm -f *.out
for i in *.toml; do
echo -n $i
../toml_cat $i >& $i.out
if [ -f $i.res ]; then
if $(diff $i.out $i.res >& /dev/null); then
echo " [OK]"
else
echo " [FAILED]"
fi
else
echo " [?????]"
fi
done

13
third_party/tomlc99/stdex/arr1.toml vendored Normal file
View file

@ -0,0 +1,13 @@
integers = [ 1, 2, 3 ]
colors = [ "red", "yellow", "green" ]
nested_arrays_of_ints = [ [ 1, 2 ], [3, 4, 5] ]
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
string_array = [ "all", 'strings', """are the same""", '''type''' ]
# Mixed-type arrays are allowed
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
contributors = [
"Foo Bar <foo@example.com>",
{ name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
]

56
third_party/tomlc99/stdex/arr1.toml.res vendored Normal file
View file

@ -0,0 +1,56 @@
{
integers = [
1,
2,
3,
],
colors = [
"red",
"yellow",
"green",
],
nested_arrays_of_ints = [
[
1,
2,
],
[
3,
4,
5,
],
],
nested_mixed_array = [
[
1,
2,
],
[
"a",
"b",
"c",
],
],
string_array = [
"all",
"strings",
"are the same",
"type",
],
numbers = [
0.100000,
0.200000,
0.500000,
1,
2,
5,
],
contributors = [
"Foo Bar <foo@example.com>",
{
name = "Baz Qux",
email = "bazqux@example.com",
url = "https://example.com/bazqux",
},
],
}

8
third_party/tomlc99/stdex/arr2.toml vendored Normal file
View file

@ -0,0 +1,8 @@
integers2 = [
1, 2, 3
]
integers3 = [
1,
2, # this is ok
]

11
third_party/tomlc99/stdex/arr2.toml.res vendored Normal file
View file

@ -0,0 +1,11 @@
{
integers2 = [
1,
2,
3,
],
integers3 = [
1,
2,
],
}

11
third_party/tomlc99/stdex/arrtab1.toml vendored Normal file
View file

@ -0,0 +1,11 @@
[[products]]
name = "Hammer"
sku = 738594937
[[products]] # empty table within the array
[[products]]
name = "Nail"
sku = 284758393
color = "gray"

View file

@ -0,0 +1,15 @@
{
products = [
{
name = "Hammer",
sku = 738594937,
},
{
},
{
name = "Nail",
sku = 284758393,
color = "gray",
},
],
}

19
third_party/tomlc99/stdex/arrtab2.toml vendored Normal file
View file

@ -0,0 +1,19 @@
[[fruits]]
name = "apple"
[fruits.physical] # subtable
color = "red"
shape = "round"
[[fruits.varieties]] # nested array of tables
name = "red delicious"
[[fruits.varieties]]
name = "granny smith"
[[fruits]]
name = "banana"
[[fruits.varieties]]
name = "plantain"

View file

@ -0,0 +1,27 @@
{
fruits = [
{
name = "apple",
varieties = [
{
name = "red delicious",
},
{
name = "granny smith",
},
],
physical = {
color = "red",
shape = "round",
},
},
{
name = "banana",
varieties = [
{
name = "plantain",
},
],
},
],
}

View file

@ -0,0 +1,8 @@
# INVALID TOML DOC
[fruit.physical] # subtable, but to which parent element should it belong?
color = "red"
shape = "round"
[[fruit]] # parser must throw an error upon discovering that "fruit" is
# an array rather than a table
name = "apple"

View file

@ -0,0 +1 @@
ERROR: line 6: key exists

View file

@ -0,0 +1,4 @@
# INVALID TOML DOC
fruits = []
[[fruits]] # Not allowed

View file

@ -0,0 +1 @@
ERROR: line 4: array mismatch

11
third_party/tomlc99/stdex/arrtab5.toml vendored Normal file
View file

@ -0,0 +1,11 @@
# INVALID TOML DOC
[[fruits]]
name = "apple"
[[fruits.varieties]]
name = "red delicious"
# INVALID: This table conflicts with the previous array of tables
[fruits.varieties]
name = "granny smith"

View file

@ -0,0 +1 @@
ERROR: line 9: key exists

14
third_party/tomlc99/stdex/arrtab6.toml vendored Normal file
View file

@ -0,0 +1,14 @@
# INVALID TOML DOC
[[fruits]]
name = "apple"
[[fruits.varieties]]
name = "red delicious"
[fruits.physical]
color = "red"
shape = "round"
# INVALID: This array of tables conflicts with the previous table
[[fruits.physical]]
color = "green"

View file

@ -0,0 +1 @@
ERROR: line 13: key exists

View file

@ -0,0 +1,3 @@
points = [ { x = 1, y = 2, z = 3 },
{ x = 7, y = 8, z = 9 },
{ x = 2, y = 4, z = 8 } ]

View file

@ -0,0 +1,19 @@
{
points = [
{
x = 1,
y = 2,
z = 3,
},
{
x = 7,
y = 8,
z = 9,
},
{
x = 2,
y = 4,
z = 8,
},
],
}

3
third_party/tomlc99/stdex/bool1.toml vendored Normal file
View file

@ -0,0 +1,3 @@
bool1 = true
bool2 = false

View file

@ -0,0 +1,4 @@
{
bool1 = true,
bool2 = false,
}

View file

@ -0,0 +1,3 @@
# This is a full-line comment
key = "value" # This is a comment at the end of a line
another = "# This is not a comment"

View file

@ -0,0 +1,4 @@
{
key = "value",
another = "# This is not a comment",
}

13
third_party/tomlc99/stdex/float1.toml vendored Normal file
View file

@ -0,0 +1,13 @@
# fractional
flt1 = +1.0
flt2 = 3.1415
flt3 = -0.01
# exponent
flt4 = 5e+22
flt5 = 1e06
flt6 = -2E-2
# both
flt7 = 6.626e-34

View file

@ -0,0 +1,9 @@
{
flt1 = 1.000000,
flt2 = 3.141500,
flt3 = -0.010000,
flt4 = 49999999999999995805696.000000,
flt5 = 1000000.000000,
flt6 = -0.020000,
flt7 = 0.000000,
}

1
third_party/tomlc99/stdex/float2.toml vendored Normal file
View file

@ -0,0 +1 @@
invalid_float_1 = .7

View file

@ -0,0 +1,2 @@
{
ERROR: unable to decode value in table

2
third_party/tomlc99/stdex/float3.toml vendored Normal file
View file

@ -0,0 +1,2 @@
invalid_float_2 = 7.

View file

@ -0,0 +1,2 @@
{
ERROR: unable to decode value in table

1
third_party/tomlc99/stdex/float4.toml vendored Normal file
View file

@ -0,0 +1 @@
invalid_float_3 = 3.e+20

View file

@ -0,0 +1,2 @@
{
ERROR: unable to decode value in table

1
third_party/tomlc99/stdex/float5.toml vendored Normal file
View file

@ -0,0 +1 @@
flt8 = 224_617.445_991_228

View file

@ -0,0 +1,3 @@
{
flt8 = 224617.445991,
}

10
third_party/tomlc99/stdex/float6.toml vendored Normal file
View file

@ -0,0 +1,10 @@
# infinity
sf1 = inf # positive infinity
sf2 = +inf # positive infinity
sf3 = -inf # negative infinity
# not a number
sf4 = nan # actual sNaN/qNaN encoding is implementation-specific
sf5 = +nan # same as `nan`
sf6 = -nan # valid, actual encoding is implementation-specific

Some files were not shown because too many files have changed in this diff Show more