silkedit 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rbcli +0 -0
- data/CHANGELOG.md +7 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +169 -0
- data/README.md +302 -0
- data/Rakefile +8 -0
- data/exe/silkedit +13 -0
- data/lib/commands/backup_restore.rb +25 -0
- data/lib/commands/cheat.rb +74 -0
- data/lib/commands/edit_diff.rb +47 -0
- data/lib/commands/examples/command.rb +51 -0
- data/lib/commands/examples/script.rb +36 -0
- data/lib/commands/journal.rb +34 -0
- data/lib/commands/permasave_permaload.rb +62 -0
- data/lib/commands/scripts/.keep +0 -0
- data/lib/commands/unpack_repack.rb +27 -0
- data/lib/commands/zone_mkzone.rb +103 -0
- data/lib/config/config.rb +28 -0
- data/lib/config/envvars.rb +23 -0
- data/lib/config/hooks.rb +22 -0
- data/lib/config/logger.rb +36 -0
- data/lib/config/parser.rb +34 -0
- data/lib/config/updatechecker.rb +12 -0
- data/lib/silkedit/cheats/cheatengine.rb +33 -0
- data/lib/silkedit/cheats/hollow_knight_cheats.rb +5 -0
- data/lib/silkedit/cheats/merger.rb +107 -0
- data/lib/silkedit/cheats/silksong_cheats.rb +161 -0
- data/lib/silkedit/cheats/silksong_enemyjournal.rb +120 -0
- data/lib/silkedit/cheats/silksong_zoner.rb +98 -0
- data/lib/silkedit/config/savegame.yaml +13 -0
- data/lib/silkedit/config/silkedit.yaml +6 -0
- data/lib/silkedit/config/silksong/cheatdata.yaml +1341 -0
- data/lib/silkedit/config/silksong/enemylist.yaml +1424 -0
- data/lib/silkedit/config/silksong/old.yaml +4345 -0
- data/lib/silkedit/config/silksong/permasaves.yaml +12 -0
- data/lib/silkedit/config/silksong/unfinished.yaml +628 -0
- data/lib/silkedit/config/silksong/zones.yaml +1738 -0
- data/lib/silkedit/images/.keep +0 -0
- data/lib/silkedit/images/silksong/Aknid.png +0 -0
- data/lib/silkedit/images/silksong/Alita.png +0 -0
- data/lib/silkedit/images/silksong/Barnak.png +0 -0
- data/lib/silkedit/images/silksong/Beastfly.png +0 -0
- data/lib/silkedit/images/silksong/Bell_Beast.png +0 -0
- data/lib/silkedit/images/silksong/Bell_Eater.png +0 -0
- data/lib/silkedit/images/silksong/Bloatroach.png +0 -0
- data/lib/silkedit/images/silksong/Broodmother.png +0 -0
- data/lib/silkedit/images/silksong/Brushflit.png +0 -0
- data/lib/silkedit/images/silksong/Burning_Bug.png +0 -0
- data/lib/silkedit/images/silksong/Caranid.png +0 -0
- data/lib/silkedit/images/silksong/Choir_Bellbearer.png +0 -0
- data/lib/silkedit/images/silksong/Choir_Clapper.png +0 -0
- data/lib/silkedit/images/silksong/Choir_Elder.png +0 -0
- data/lib/silkedit/images/silksong/Choir_Flyer.png +0 -0
- data/lib/silkedit/images/silksong/Choir_Hornhead.png +0 -0
- data/lib/silkedit/images/silksong/Choir_Pouncer.png +0 -0
- data/lib/silkedit/images/silksong/Choristor.png +0 -0
- data/lib/silkedit/images/silksong/Clawmaiden.png +0 -0
- data/lib/silkedit/images/silksong/Clover_Dancers.png +0 -0
- data/lib/silkedit/images/silksong/Cloverstag.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Choirbug.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Clapper.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Cleanser.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Crawler.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Dancers.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Defender.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Hauler.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Spine.png +0 -0
- data/lib/silkedit/images/silksong/Cogwork_Underfly.png +0 -0
- data/lib/silkedit/images/silksong/Cogworker.png +0 -0
- data/lib/silkedit/images/silksong/Conchfly.png +0 -0
- data/lib/silkedit/images/silksong/Coral_Furm.png +0 -0
- data/lib/silkedit/images/silksong/Corrcrust_Karaka.png +0 -0
- data/lib/silkedit/images/silksong/Covetous_Pilgrim.png +0 -0
- data/lib/silkedit/images/silksong/Craggler.png +0 -0
- data/lib/silkedit/images/silksong/Cragglite.png +0 -0
- data/lib/silkedit/images/silksong/Craw.png +0 -0
- data/lib/silkedit/images/silksong/Craw_Juror.png +0 -0
- data/lib/silkedit/images/silksong/Crawfather.png +0 -0
- data/lib/silkedit/images/silksong/Crust_King_Khann.png +0 -0
- data/lib/silkedit/images/silksong/Crustcrag.png +0 -0
- data/lib/silkedit/images/silksong/Crustcrawler.png +0 -0
- data/lib/silkedit/images/silksong/Deep_Diver.png +0 -0
- data/lib/silkedit/images/silksong/Disgraced_Chef_Lugoli.png +0 -0
- data/lib/silkedit/images/silksong/Drapefly.png +0 -0
- data/lib/silkedit/images/silksong/Drapelord.png +0 -0
- data/lib/silkedit/images/silksong/Drapemite.png +0 -0
- data/lib/silkedit/images/silksong/Dreg_Catcher.png +0 -0
- data/lib/silkedit/images/silksong/Dreg_Husk.png +0 -0
- data/lib/silkedit/images/silksong/Dregwheel.png +0 -0
- data/lib/silkedit/images/silksong/Driftlin.png +0 -0
- data/lib/silkedit/images/silksong/Driznarga.png +0 -0
- data/lib/silkedit/images/silksong/Driznit.png +0 -0
- data/lib/silkedit/images/silksong/Ductsucker.png +0 -0
- data/lib/silkedit/images/silksong/Elder_Pilgrim.png +0 -0
- data/lib/silkedit/images/silksong/Envoy.png +0 -0
- data/lib/silkedit/images/silksong/Escalion.png +0 -0
- data/lib/silkedit/images/silksong/Father_of_the_Flame.png +0 -0
- data/lib/silkedit/images/silksong/Fertid.png +0 -0
- data/lib/silkedit/images/silksong/First_Sinner.png +0 -0
- data/lib/silkedit/images/silksong/Flapping_Fertid.png +0 -0
- data/lib/silkedit/images/silksong/Flintbeetle.png +0 -0
- data/lib/silkedit/images/silksong/Flintflame_Flyer.png +0 -0
- data/lib/silkedit/images/silksong/Flintstone_Flyer.png +0 -0
- data/lib/silkedit/images/silksong/Fluttermite.png +0 -0
- data/lib/silkedit/images/silksong/Forebrothers_Signis_&_Gron.png +0 -0
- data/lib/silkedit/images/silksong/Fourth_Chorus.png +0 -0
- data/lib/silkedit/images/silksong/Freshfly.png +0 -0
- data/lib/silkedit/images/silksong/Furm.png +0 -0
- data/lib/silkedit/images/silksong/Gahlia.png +0 -0
- data/lib/silkedit/images/silksong/Gargant_Gloom.png +0 -0
- data/lib/silkedit/images/silksong/Garpid.png +0 -0
- data/lib/silkedit/images/silksong/Giant_Drapemite.png +0 -0
- data/lib/silkedit/images/silksong/Gloomsac.png +0 -0
- data/lib/silkedit/images/silksong/Grand_Mother_Silk.png +0 -0
- data/lib/silkedit/images/silksong/Grand_Reed.png +0 -0
- data/lib/silkedit/images/silksong/Great_Conchfly.png +0 -0
- data/lib/silkedit/images/silksong/Groal_the_Great.png +0 -0
- data/lib/silkedit/images/silksong/Grom.png +0 -0
- data/lib/silkedit/images/silksong/Gromling.png +0 -0
- data/lib/silkedit/images/silksong/Guardfly.png +0 -0
- data/lib/silkedit/images/silksong/Gurr_the_Outcast.png +0 -0
- data/lib/silkedit/images/silksong/Hardbone_Elder.png +0 -0
- data/lib/silkedit/images/silksong/Hardbone_Hopper.png +0 -0
- data/lib/silkedit/images/silksong/Hoker.png +0 -0
- data/lib/silkedit/images/silksong/Huge_Flea.png +0 -0
- data/lib/silkedit/images/silksong/Imoba.png +0 -0
- data/lib/silkedit/images/silksong/Judge.png +0 -0
- data/lib/silkedit/images/silksong/Kai.png +0 -0
- data/lib/silkedit/images/silksong/Kakri.png +0 -0
- data/lib/silkedit/images/silksong/Karak_Gor.png +0 -0
- data/lib/silkedit/images/silksong/Karaka.png +0 -0
- data/lib/silkedit/images/silksong/Kilik.png +0 -0
- data/lib/silkedit/images/silksong/Kindanir.png +0 -0
- data/lib/silkedit/images/silksong/Lace.png +0 -0
- data/lib/silkedit/images/silksong/Lampbearer.png +0 -0
- data/lib/silkedit/images/silksong/Last_Claw.png +0 -0
- data/lib/silkedit/images/silksong/Last_Judge.png +0 -0
- data/lib/silkedit/images/silksong/Lavalarga.png +0 -0
- data/lib/silkedit/images/silksong/Lavalug.png +0 -0
- data/lib/silkedit/images/silksong/Leaf_Glider.png +0 -0
- data/lib/silkedit/images/silksong/Leaf_Roller.png +0 -0
- data/lib/silkedit/images/silksong/Lost_Garmond.png +0 -0
- data/lib/silkedit/images/silksong/Lost_Lace.png +0 -0
- data/lib/silkedit/images/silksong/Maestro.png +0 -0
- data/lib/silkedit/images/silksong/Marrowmaw.png +0 -0
- data/lib/silkedit/images/silksong/Massive_Mossgrub.png +0 -0
- data/lib/silkedit/images/silksong/Mawling.png +0 -0
- data/lib/silkedit/images/silksong/Memoria.png +0 -0
- data/lib/silkedit/images/silksong/Minister.png +0 -0
- data/lib/silkedit/images/silksong/Miremite.png +0 -0
- data/lib/silkedit/images/silksong/Mite.png +0 -0
- data/lib/silkedit/images/silksong/Mitemother.png +0 -0
- data/lib/silkedit/images/silksong/Mnemonid.png +0 -0
- data/lib/silkedit/images/silksong/Mnemonord.png +0 -0
- data/lib/silkedit/images/silksong/Moorwing.png +0 -0
- data/lib/silkedit/images/silksong/Mortician.png +0 -0
- data/lib/silkedit/images/silksong/Moss_Mother.png +0 -0
- data/lib/silkedit/images/silksong/Mossgrub.png +0 -0
- data/lib/silkedit/images/silksong/Mossmir.png +0 -0
- data/lib/silkedit/images/silksong/Mothleaf_Lagnia.png +0 -0
- data/lib/silkedit/images/silksong/Muckmaggot.png +0 -0
- data/lib/silkedit/images/silksong/Muckroach.png +0 -0
- data/lib/silkedit/images/silksong/Nuphar.png +0 -0
- data/lib/silkedit/images/silksong/Nyleth.png +0 -0
- data/lib/silkedit/images/silksong/Overgrown_Pilgrim.png +0 -0
- data/lib/silkedit/images/silksong/Palestag.png +0 -0
- data/lib/silkedit/images/silksong/Pendra.png +0 -0
- data/lib/silkedit/images/silksong/Pendragor.png +0 -0
- data/lib/silkedit/images/silksong/Penitent.png +0 -0
- data/lib/silkedit/images/silksong/Phacia.png +0 -0
- data/lib/silkedit/images/silksong/Phantom.png +0 -0
- data/lib/silkedit/images/silksong/Pharlid.png +0 -0
- data/lib/silkedit/images/silksong/Pharlid_Diver.png +0 -0
- data/lib/silkedit/images/silksong/Pilgrim_Bellbearer.png +0 -0
- data/lib/silkedit/images/silksong/Pilgrim_Groveller.png +0 -0
- data/lib/silkedit/images/silksong/Pilgrim_Guide.png +0 -0
- data/lib/silkedit/images/silksong/Pilgrim_Hiker.png +0 -0
- data/lib/silkedit/images/silksong/Pilgrim_Hornfly.png +0 -0
- data/lib/silkedit/images/silksong/Pilgrim_Hulk.png +0 -0
- data/lib/silkedit/images/silksong/Pilgrim_Pouncer.png +0 -0
- data/lib/silkedit/images/silksong/Pinstress.png +0 -0
- data/lib/silkedit/images/silksong/Plasmid.png +0 -0
- data/lib/silkedit/images/silksong/Plasmidas.png +0 -0
- data/lib/silkedit/images/silksong/Plasmified_Zango.png +0 -0
- data/lib/silkedit/images/silksong/Pokenabbin.png +0 -0
- data/lib/silkedit/images/silksong/Pollenica.png +0 -0
- data/lib/silkedit/images/silksong/Pond_Skipper.png +0 -0
- data/lib/silkedit/images/silksong/Pondcatcher.png +0 -0
- data/lib/silkedit/images/silksong/Puny_Penitent.png +0 -0
- data/lib/silkedit/images/silksong/Reed.png +0 -0
- data/lib/silkedit/images/silksong/Rhinogrund.png +0 -0
- data/lib/silkedit/images/silksong/Roachcatcher.png +0 -0
- data/lib/silkedit/images/silksong/Roachfeeder.png +0 -0
- data/lib/silkedit/images/silksong/Roachkeeper.png +0 -0
- data/lib/silkedit/images/silksong/Roachserver.png +0 -0
- data/lib/silkedit/images/silksong/Sandcarver.png +0 -0
- data/lib/silkedit/images/silksong/Savage_Beastfly.png +0 -0
- data/lib/silkedit/images/silksong/Scabfly.png +0 -0
- data/lib/silkedit/images/silksong/Scrollreader.png +0 -0
- data/lib/silkedit/images/silksong/Second_Sentinel.png +0 -0
- data/lib/silkedit/images/silksong/Servitor_Boran.png +0 -0
- data/lib/silkedit/images/silksong/Servitor_Ignim.png +0 -0
- data/lib/silkedit/images/silksong/Shadow_Charger.png +0 -0
- data/lib/silkedit/images/silksong/Shadow_Creeper_(Silksong).png +0 -0
- data/lib/silkedit/images/silksong/Shardillard.png +0 -0
- data/lib/silkedit/images/silksong/Shellwood_Gnat.png +0 -0
- data/lib/silkedit/images/silksong/Shrine_Guardian_Seth.png +0 -0
- data/lib/silkedit/images/silksong/Silk_Snipper.png +0 -0
- data/lib/silkedit/images/silksong/Sister_Splinter.png +0 -0
- data/lib/silkedit/images/silksong/Skarr_Scout.png +0 -0
- data/lib/silkedit/images/silksong/Skarr_Stalker.png +0 -0
- data/lib/silkedit/images/silksong/Skarrgard.png +0 -0
- data/lib/silkedit/images/silksong/Skarrlid.png +0 -0
- data/lib/silkedit/images/silksong/Skarrsinger_Karmelita.png +0 -0
- data/lib/silkedit/images/silksong/Skarrwing.png +0 -0
- data/lib/silkedit/images/silksong/Skrill.png +0 -0
- data/lib/silkedit/images/silksong/Skull_Brute.png +0 -0
- data/lib/silkedit/images/silksong/Skull_Scuttler.png +0 -0
- data/lib/silkedit/images/silksong/Skull_Tyrant.png +0 -0
- data/lib/silkedit/images/silksong/Skullwing.png +0 -0
- data/lib/silkedit/images/silksong/Slubberlug.png +0 -0
- data/lib/silkedit/images/silksong/Smelt_Shoveller.png +0 -0
- data/lib/silkedit/images/silksong/Smokerock_Sifter.png +0 -0
- data/lib/silkedit/images/silksong/Snitchfly.png +0 -0
- data/lib/silkedit/images/silksong/Spear_Skarr.png +0 -0
- data/lib/silkedit/images/silksong/Spinebeak_Kai.png +0 -0
- data/lib/silkedit/images/silksong/Spit_Squit.png +0 -0
- data/lib/silkedit/images/silksong/Splinter.png +0 -0
- data/lib/silkedit/images/silksong/Splinterbark.png +0 -0
- data/lib/silkedit/images/silksong/Splinterhorn.png +0 -0
- data/lib/silkedit/images/silksong/Squatcraw.png +0 -0
- data/lib/silkedit/images/silksong/Squatcraw_Juror.png +0 -0
- data/lib/silkedit/images/silksong/Squirrm.png +0 -0
- data/lib/silkedit/images/silksong/Steelspine_Kai.png +0 -0
- data/lib/silkedit/images/silksong/Stilkin.png +0 -0
- data/lib/silkedit/images/silksong/Stilkin_Trapper.png +0 -0
- data/lib/silkedit/images/silksong/Summoned_Saviour.png +0 -0
- data/lib/silkedit/images/silksong/Surgeon.png +0 -0
- data/lib/silkedit/images/silksong/Swamp_Squit.png +0 -0
- data/lib/silkedit/images/silksong/Tallcraw.png +0 -0
- data/lib/silkedit/images/silksong/Tallcraw_Juror.png +0 -0
- data/lib/silkedit/images/silksong/Tarmite.png +0 -0
- data/lib/silkedit/images/silksong/The_Unravelled.png +0 -0
- data/lib/silkedit/images/silksong/Thread_Raker.png +0 -0
- data/lib/silkedit/images/silksong/Tormented_Trobbio.png +0 -0
- data/lib/silkedit/images/silksong/Trobbio.png +0 -0
- data/lib/silkedit/images/silksong/Undercrank.png +0 -0
- data/lib/silkedit/images/silksong/Underloft.png +0 -0
- data/lib/silkedit/images/silksong/Underpoke.png +0 -0
- data/lib/silkedit/images/silksong/Underscrub.png +0 -0
- data/lib/silkedit/images/silksong/Undersweep.png +0 -0
- data/lib/silkedit/images/silksong/Underworker.png +0 -0
- data/lib/silkedit/images/silksong/Vaultborn.png +0 -0
- data/lib/silkedit/images/silksong/Vaultkeeper.png +0 -0
- data/lib/silkedit/images/silksong/Verdanir.png +0 -0
- data/lib/silkedit/images/silksong/Vicious_Caranid.png +0 -0
- data/lib/silkedit/images/silksong/Void_Mass.png +0 -0
- data/lib/silkedit/images/silksong/Void_Tendrils_(Silksong).png +0 -0
- data/lib/silkedit/images/silksong/Voltvyrm.png +0 -0
- data/lib/silkedit/images/silksong/Wardenfly.png +0 -0
- data/lib/silkedit/images/silksong/Watcher_at_the_Edge.png +0 -0
- data/lib/silkedit/images/silksong/Widow.png +0 -0
- data/lib/silkedit/images/silksong/Winged_Furm.png +0 -0
- data/lib/silkedit/images/silksong/Winged_Lifeseed.png +0 -0
- data/lib/silkedit/images/silksong/Winged_Pilgrim.png +0 -0
- data/lib/silkedit/images/silksong/Winged_Pilgrim_Bellbearer.png +0 -0
- data/lib/silkedit/images/silksong/Wingmould_(Silksong).png +0 -0
- data/lib/silkedit/images/silksong/Wisp.png +0 -0
- data/lib/silkedit/images/silksong/Wood_Wasp.png +0 -0
- data/lib/silkedit/images/silksong/Wraith.png +0 -0
- data/lib/silkedit/images/silksong/Yago.png +0 -0
- data/lib/silkedit/images/silksong/Yuma.png +0 -0
- data/lib/silkedit/images/silksong/Yumama.png +0 -0
- data/lib/silkedit/savegame/crypto.rb +25 -0
- data/lib/silkedit/savegame/diff.rb +159 -0
- data/lib/silkedit/savegame/packer.rb +75 -0
- data/lib/silkedit/savegame/savefile.rb +157 -0
- data/lib/silkedit/util/system.rb +37 -0
- data/lib/silkedit/version.rb +5 -0
- data/lib/silkedit.rb +9 -0
- data/sig/silkedit.rbs +4 -0
- metadata +505 -0
data/Rakefile
ADDED
data/exe/silkedit
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
################
|
|
4
|
+
### Silkedit ###
|
|
5
|
+
################
|
|
6
|
+
|
|
7
|
+
require 'rbcli'
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'silkedit')
|
|
10
|
+
Dir[File.join(File.dirname(__FILE__), '..', 'lib', 'config', '*.rb')].each { |file| require file }
|
|
11
|
+
Dir[File.join(File.dirname(__FILE__), '..', 'lib', 'commands', '*.rb')].each { |file| require file }
|
|
12
|
+
|
|
13
|
+
Rbcli.go!
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Rbcli.command 'backup' do
|
|
2
|
+
description 'Backs up the savefile'
|
|
3
|
+
parameter :custom_name, 'Give the backup a custom name. Named backups can\'t be edited.', short: :n, type: :string
|
|
4
|
+
action do |opts, params, args, config, env|
|
|
5
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
6
|
+
s.direct_backup(backup_name: params[:custom_name])
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
Rbcli.command 'restore' do
|
|
11
|
+
description 'Restore a backup to the savefile. Providing no parameters restores the latest backup.'
|
|
12
|
+
parameter :backup_seq, 'Backup number to restore (Can\'t use together with named backup)', short: :b, type: :integer
|
|
13
|
+
parameter :backup_name, 'Named backup to restore', short: :n, type: :string
|
|
14
|
+
|
|
15
|
+
action do |opts, params, args, config, env|
|
|
16
|
+
if !params[:backup_seq].nil? && !params[:backup_name].nil?
|
|
17
|
+
Rbcli.log.error 'Can\'t specify both a sequence and name at the same time.'
|
|
18
|
+
else
|
|
19
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
20
|
+
unless s.direct_restore(seq_number: params[:backup_seq], backup_name: params[:backup_name])
|
|
21
|
+
Rbcli.log.error "Failed to restore backup"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Rbcli.command 'cheat' do
|
|
2
|
+
description 'Applies one or more cheats to the selected savefile'
|
|
3
|
+
usage '<cheat1> <cheat2> <cheat3>...'
|
|
4
|
+
parameter :list, 'List all cheats', type: :bool, default: false
|
|
5
|
+
# parameter :force, "Force application of a cheat even when requirements aren't met. Additional changes may be made to your savegave.", type: :bool, default: false
|
|
6
|
+
action do |opts, params, args, config, env|
|
|
7
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
8
|
+
s.load_from_dat
|
|
9
|
+
c = Silkedit::Cheat::Engine.new(s.data)
|
|
10
|
+
|
|
11
|
+
display_simple_list = lambda do |list, cols|
|
|
12
|
+
max_length = list.map(&:length).max
|
|
13
|
+
display_set = []
|
|
14
|
+
rows = (list.length / cols.to_f).ceil
|
|
15
|
+
row_idx = 0
|
|
16
|
+
max_rows = rows - 1
|
|
17
|
+
list.length.times do |i|
|
|
18
|
+
display_set[row_idx] ||= []
|
|
19
|
+
display_set[row_idx] << list[i]
|
|
20
|
+
row_idx += 1
|
|
21
|
+
row_idx = 0 if row_idx > max_rows
|
|
22
|
+
end
|
|
23
|
+
display_set.map { |row| row.map { |z| z.ljust(max_length) }.join(' ') }.join("\n")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if args.empty? || params[:list]
|
|
27
|
+
Rbcli.log.info 'Cheats:'
|
|
28
|
+
Rbcli.log.info display_simple_list.call(c.list_cheats, 5)
|
|
29
|
+
Rbcli.exit(0)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
changes = args.map do |cht|
|
|
33
|
+
cht = cht.downcase
|
|
34
|
+
status = c.apply_cheat(cht)
|
|
35
|
+
case status
|
|
36
|
+
when :no_cheat
|
|
37
|
+
Rbcli.log.warn "Could not apply cheat #{cht}: Cheat does not exist"
|
|
38
|
+
Rbcli.log.info 'Did you mean one of these?'
|
|
39
|
+
possible_cheats = c.list_cheats.select { |cheat| cheat.include?(cht) }
|
|
40
|
+
Rbcli.log.info display_simple_list.call(possible_cheats, 5)
|
|
41
|
+
nil
|
|
42
|
+
when :failed_act_check
|
|
43
|
+
Rbcli.log.warn "Could not apply cheat #{cht.colorize(:red)}: The player is in the wrong act. Use --(f)orce to override."
|
|
44
|
+
nil
|
|
45
|
+
when :failed_soft_reqs
|
|
46
|
+
Rbcli.log.warn "Could not apply cheat #{cht.colorize(:red)}: Soft requirements not met. Use --(f)orce to apply the required changes."
|
|
47
|
+
nil
|
|
48
|
+
when :failed_hard_reqs
|
|
49
|
+
Rbcli.log.error "Could not apply cheat #{cht.colorize(:red)}: Hard requirements not met. Applying the cheat would cause in-game errors."
|
|
50
|
+
nil
|
|
51
|
+
when :success
|
|
52
|
+
Rbcli.log.info " Success!".colorize(:green)
|
|
53
|
+
cht
|
|
54
|
+
else
|
|
55
|
+
raise "Unknown status: #{status}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if changes.empty?
|
|
60
|
+
Rbcli.log.info ''
|
|
61
|
+
Rbcli.log.info 'No cheats applied'
|
|
62
|
+
Rbcli.exit(0)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if changes.include?(nil)
|
|
66
|
+
Rbcli.log.info ''
|
|
67
|
+
Rbcli.log.info 'Some cheats failed to apply. Discarding changes.'
|
|
68
|
+
Rbcli.exit(0)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
s.direct_backup
|
|
72
|
+
s.save_to_dat
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
Rbcli.command 'edit' do
|
|
2
|
+
description 'Edit the savefile directly'
|
|
3
|
+
action do |opts, params, args, config, env|
|
|
4
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
5
|
+
s.load_from_dat
|
|
6
|
+
s.save_to_json
|
|
7
|
+
Process.wait(Process.spawn(config[:editor_command].sub('%FILE%', s.filenames[:json])))
|
|
8
|
+
if Silkedit::Sys.yes_no?('Apply changes?')
|
|
9
|
+
s.load_from_json
|
|
10
|
+
s.direct_backup
|
|
11
|
+
s.save_to_dat
|
|
12
|
+
Rbcli.log.info 'Updated savefile'
|
|
13
|
+
else
|
|
14
|
+
Rbcli.log.info 'Aborted'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Rbcli.command 'diff' do
|
|
20
|
+
description 'Diffs the current savegame against the latest backup, a specified backup, or a different save'
|
|
21
|
+
parameter :backup_seq, 'Backup number to diff against', short: :b, type: :integer
|
|
22
|
+
parameter :othersave, 'Other save number to diff against', short: :o, type: :integer
|
|
23
|
+
parameter :yaml_output, 'Output in YAML instead of a Ruby object', short: :y, type: :boolean
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
action do |opts, params, args, config, env|
|
|
27
|
+
new = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
28
|
+
new.load_from_dat
|
|
29
|
+
if params[:othersave]
|
|
30
|
+
old = Silkedit::Savegame::SaveFile.new(:silksong, params[:othersave])
|
|
31
|
+
old.load_from_dat
|
|
32
|
+
else
|
|
33
|
+
old = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
34
|
+
old.load_from_backup(seq_number: params[:backup_seq])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
diff = Silkedit::Savegame::Diff.mkdiff(old.data, new.data)
|
|
38
|
+
Rbcli.log.info Silkedit::Savegame::Diff.parse_diff(diff, yaml_output: params[:yaml_output])
|
|
39
|
+
|
|
40
|
+
# s.save_as_json
|
|
41
|
+
# FileUtils.mv(s.json_filename, "#{s.json_filename}.old")
|
|
42
|
+
# s.load_from_dat
|
|
43
|
+
# s.save_as_json
|
|
44
|
+
# FileUtils.mv(s.json_filename, "#{s.json_filename}.new")
|
|
45
|
+
# Process.wait(Process.spawn(config[:diff_command].sub('%OLD%', "#{s.json_filename}.old").sub('%NEW%', "#{s.json_filename}.new")))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Rbcli.command "example" do
|
|
2
|
+
##### Command Declaration (At least one is required) #####
|
|
3
|
+
# default (Optional) The default command is run when no other commands are called on the CLI
|
|
4
|
+
# Note that parameters are not available for default commands, as all CLI options
|
|
5
|
+
# are parsed against the global-level ones declared in the `Configurate.opts` block
|
|
6
|
+
# description (Optional) Short description that shows up in --help for the executable
|
|
7
|
+
# usage (Optional) Usage text that shows up in --help or when CLI format is bad
|
|
8
|
+
# helptext (Optional) Large help text that shows up in --help for the command
|
|
9
|
+
# default
|
|
10
|
+
description 'Example command'
|
|
11
|
+
usage "[--param|--otherparam] name"
|
|
12
|
+
helptext <<~EOF
|
|
13
|
+
Big block of helptext
|
|
14
|
+
EOF
|
|
15
|
+
# parameter (Optinoal) Parameters follow the same format as CLI Options, but are only available for this command
|
|
16
|
+
parameter :param, 'A Parameter', default: false
|
|
17
|
+
parameter :otherparam, 'Another Parameter', type: :string, default: "Default value"
|
|
18
|
+
# action (Required, unless declaring a `script`) The action block is code that gets executed when the command is called
|
|
19
|
+
# Sending all output through the logger is recommended. For it to be displayed
|
|
20
|
+
# as regular text, set the logger to the :display format
|
|
21
|
+
action do |opts, params, args, config, env|
|
|
22
|
+
Rbcli.log.info "Welcome to your new application!"
|
|
23
|
+
Rbcli.log.info "We like to send all of our output through the logger for easy formatting and deployment..."
|
|
24
|
+
puts "...but you don't have to"
|
|
25
|
+
Rbcli.log.info "Here's a quick demo of how to use the framework:\n"
|
|
26
|
+
|
|
27
|
+
Rbcli.log.info "Top-level CLI Options: " + opts.to_s
|
|
28
|
+
Rbcli.log.info "Parameters: " + params.to_s
|
|
29
|
+
Rbcli.log.info "Arguments on the CLI: " + args.to_s
|
|
30
|
+
Rbcli.log.info "The config: " + config.to_s
|
|
31
|
+
Rbcli.log.info "Environment variables: " + env.to_s
|
|
32
|
+
Rbcli.log.info ""
|
|
33
|
+
|
|
34
|
+
Rbcli.log.debug "Example Debug Message (change your log level to see this!)", "MYAPP"
|
|
35
|
+
Rbcli.log.info "Example Info Message", "MYAPP"
|
|
36
|
+
Rbcli.log.warn "Example Warning Message", "MYAPP"
|
|
37
|
+
Rbcli.log.error "Example Error Message", "MYAPP"
|
|
38
|
+
Rbcli.log.fatal "Example Fatal Message", "MYAPP"
|
|
39
|
+
Rbcli.log.unknown "Example Unknown Message", "MYAPP"
|
|
40
|
+
Rbcli.log.info ""
|
|
41
|
+
|
|
42
|
+
config.add_default :foo, 'bar'
|
|
43
|
+
config.create!
|
|
44
|
+
config.load!
|
|
45
|
+
config[:davey] = 'Davey Jones'.compress
|
|
46
|
+
Rbcli.log.info "Compressed String: " + config[:davey]
|
|
47
|
+
Rbcli.log.info "Decompressed String: " + config[:davey].decompress
|
|
48
|
+
config.save!
|
|
49
|
+
Rbcli.log.info config
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Script Command
|
|
2
|
+
# Supports all of the same features as a regular command, but passes everything to a bash script
|
|
3
|
+
# The script can be defined inline, or a path to an external script can be provided
|
|
4
|
+
#
|
|
5
|
+
# Code is injected into the script to integrate with Rbcli.
|
|
6
|
+
# The `log` commands are integrated with the ruby logger
|
|
7
|
+
# The `rbcli` command provides a wrapper around jq that can retrieve
|
|
8
|
+
# the values of opts/params/args/config/env
|
|
9
|
+
# For more information on JQ syntax, see: https://jqlang.github.io/jq/
|
|
10
|
+
Rbcli.command "script" do
|
|
11
|
+
description "example script command"
|
|
12
|
+
# external_script vars: {}, path: "./test.sh"
|
|
13
|
+
inline_script vars: { foo: 'bar!!!' }, inline: <<~INLINE
|
|
14
|
+
#!/usr/bin/env bash
|
|
15
|
+
log "Rbcli shell integration demo!"
|
|
16
|
+
log "A custom JQ wrapper is used to parse config passed through from Rbcli"
|
|
17
|
+
log "For more information on how to use it, see: https://jqlang.github.io/jq/"
|
|
18
|
+
log ""
|
|
19
|
+
|
|
20
|
+
log "Top-level CLI Options: $(rbcli opts .)"
|
|
21
|
+
log "Parameters: $(rbcli params .)"
|
|
22
|
+
log "Arguments on the CLI: $(rbcli args .)"
|
|
23
|
+
log "Config: $(rbcli config .)"
|
|
24
|
+
log "Environment Variables: $(rbcli env .)"
|
|
25
|
+
log "Custom Var from command: $(rbcli vars .foo)"
|
|
26
|
+
log "Same variable, in environment: ${FOO}"
|
|
27
|
+
|
|
28
|
+
log "Logs are integrated too"
|
|
29
|
+
log "Example Debug (you need to change your log level to see this)" "debug"
|
|
30
|
+
log "Example Info" "info"
|
|
31
|
+
log "Example Warning" "warn"
|
|
32
|
+
log "Example Error" "error"
|
|
33
|
+
log "Example Fatal" "fatal"
|
|
34
|
+
log "Example Unknown" "unknown"
|
|
35
|
+
INLINE
|
|
36
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Rbcli.command 'journal' do
|
|
2
|
+
description 'Manages the journal of enemy kills'
|
|
3
|
+
usage '[listall|listmissing|complete|killsonly]'
|
|
4
|
+
parameter :showimages, 'Show images of the enemies', short: 'i', type: :bool, default: false
|
|
5
|
+
action do |opts, params, args, config, env|
|
|
6
|
+
command = args.first
|
|
7
|
+
if command.nil? || command.empty? || !%w[listall listmissing complete killsonly].include?(command)
|
|
8
|
+
Rbcli.log.error "Must specify an action as one of: listall, listmissing, complete, killsonly"
|
|
9
|
+
next
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
13
|
+
s.load_from_dat
|
|
14
|
+
c = Silkedit::Cheat::Engine.new(s.data)
|
|
15
|
+
|
|
16
|
+
case command
|
|
17
|
+
when 'listall'
|
|
18
|
+
c.enemy_list(only_missing: false, show_images: params[:showimages])
|
|
19
|
+
when 'listmissing'
|
|
20
|
+
c.enemy_list(only_missing: true, show_images: params[:showimages])
|
|
21
|
+
when 'complete'
|
|
22
|
+
c.update_journal(should_update_kills_only: false)
|
|
23
|
+
s.direct_backup
|
|
24
|
+
s.save_to_dat
|
|
25
|
+
when 'killsonly'
|
|
26
|
+
c.update_journal(should_update_kills_only: true)
|
|
27
|
+
s.direct_backup
|
|
28
|
+
s.save_to_dat
|
|
29
|
+
else
|
|
30
|
+
Rbcli.fatal "Unknown command: #{command}", exit_status: 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Rbcli.command 'permasave' do
|
|
2
|
+
description 'Saves a local copy of a game into the config to restore later.'
|
|
3
|
+
parameter :name, 'Name to give the savegame', short: :n, type: :string, required: true
|
|
4
|
+
action do |opts, params, args, config, env|
|
|
5
|
+
permasave_file = config[:permasave_file_location][Silkedit::Sys.os]
|
|
6
|
+
permasave_file = permasave_file.gsub('%APPDATA%', ENV['APPDATA'] || ENV['LOCALAPPDATA']) if Silkedit::Sys.os == :windows
|
|
7
|
+
permasave_file = File.expand_path(permasave_file)
|
|
8
|
+
unless File.exist?(permasave_file)
|
|
9
|
+
FileUtils.cp(File.join(Silkedit::LIBDIR, 'config', 'silksong', 'permasaves.yaml'), permasave_file)
|
|
10
|
+
end
|
|
11
|
+
permasaves = YAML.safe_load_file(permasave_file)
|
|
12
|
+
Rbcli.log.fatal('Permasaves file is corrupt. Please delete or fix it and try again.', exit_status: 1) unless permasaves.is_a?(Hash)
|
|
13
|
+
|
|
14
|
+
params[:name] = params[:name].downcase
|
|
15
|
+
if permasaves.key?(params[:name])
|
|
16
|
+
Rbcli.log.warn "Found existing permasave: #{params[:name]}"
|
|
17
|
+
next unless Silkedit::Sys.yes_no?('Overwrite?')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
21
|
+
s.load_from_dat
|
|
22
|
+
permasaves[params[:name]] = YAML.safe_dump(s.data).compress
|
|
23
|
+
File.write(permasave_file, YAML.safe_dump(permasaves))
|
|
24
|
+
|
|
25
|
+
Rbcli.log.info "Permasave #{params[:name]} saved from slot #{opts[:savenum]}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Rbcli.command 'permaload' do
|
|
30
|
+
description 'Restores a permasave into the slot'
|
|
31
|
+
parameter :name, 'Name of the permasave to load', short: :n, type: :string, required: false
|
|
32
|
+
parameter :list, 'List all permasaves', short: :l, type: :bool, default: false
|
|
33
|
+
action do |opts, params, args, config, env|
|
|
34
|
+
permasave_file = config[:permasave_file_location][Silkedit::Sys.os]
|
|
35
|
+
permasave_file = permasave_file.gsub('%APPDATA%', ENV['APPDATA'] || ENV['LOCALAPPDATA']) if Silkedit::Sys.os == :windows
|
|
36
|
+
permasave_file = File.expand_path(permasave_file)
|
|
37
|
+
unless File.exist?(permasave_file)
|
|
38
|
+
FileUtils.cp(File.join(Silkedit::LIBDIR, 'config', 'silksong', 'permasaves.yaml'), permasave_file)
|
|
39
|
+
end
|
|
40
|
+
permasaves = YAML.safe_load_file(permasave_file)
|
|
41
|
+
Rbcli.log.fatal('Permasaves file is corrupt. Please delete or fix it and try again.', exit_status: 1) unless permasaves.is_a?(Hash)
|
|
42
|
+
|
|
43
|
+
if !params[:name] && !params[:list]
|
|
44
|
+
Rbcli.log.warn 'Must provide a permasave name to load, or use --(l)ist to list all permasaves.'
|
|
45
|
+
next
|
|
46
|
+
elsif params[:list]
|
|
47
|
+
Rbcli.log.info permasaves.keys.join("\n")
|
|
48
|
+
next
|
|
49
|
+
end
|
|
50
|
+
params[:name] = params[:name].downcase
|
|
51
|
+
|
|
52
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
53
|
+
if permasaves.is_a?(Hash) && permasaves.key?(params[:name])
|
|
54
|
+
s.data = YAML.safe_load(permasaves[params[:name]].decompress)
|
|
55
|
+
s.data['profileID'] = opts[:savenum].to_i
|
|
56
|
+
s.save_to_dat
|
|
57
|
+
Rbcli.log.info "Permasave #{params[:name]} loaded to slot #{opts[:savenum]}."
|
|
58
|
+
else
|
|
59
|
+
Rbcli.log.warn "Permasave #{params[:name]} does not exist. Exiting."
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Rbcli.command 'unpack' do
|
|
2
|
+
description 'Unpacks a save file or backup to JSON/YAML for manual editing'
|
|
3
|
+
parameter :backup_seq, 'Sequence number for the backup to unpack', short: :b, type: :integer
|
|
4
|
+
action do |opts, params, args, config, env|
|
|
5
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
6
|
+
if params[:backup_seq].nil?
|
|
7
|
+
s.load_from_dat
|
|
8
|
+
s.save_to_json
|
|
9
|
+
Rbcli.log.info 'Unpacked savefile to json/yaml'
|
|
10
|
+
else
|
|
11
|
+
s.load_from_backup(seq_number: params[:backup_seq])
|
|
12
|
+
s.save_to_json
|
|
13
|
+
Rbcli.log.info "Unpacked backup ##{params[:backup_seq]}"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
Rbcli.command 'repack' do
|
|
19
|
+
description 'Packs the JSON/YAML to the savefile'
|
|
20
|
+
action do |opts, params, args, config, env|
|
|
21
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
22
|
+
s.load_from_json
|
|
23
|
+
s.direct_backup
|
|
24
|
+
s.save_to_dat
|
|
25
|
+
Rbcli.log.info 'Repacked savefile from json/yaml'
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Rbcli.command 'zone' do
|
|
2
|
+
description 'Zones the character to a different respawn point'
|
|
3
|
+
usage '<zone> (--(f)orce)'
|
|
4
|
+
parameter :list, 'Display the full list of zones to select from', type: :bool, default: false
|
|
5
|
+
parameter :force, 'Force select a spawn point even when requirements are not met. Changes may be made to your savegave.', type: :bool, default: false
|
|
6
|
+
action do |opts, params, args, config, env|
|
|
7
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
8
|
+
s.load_from_dat
|
|
9
|
+
c = Silkedit::Cheat::Engine.new(s.data)
|
|
10
|
+
|
|
11
|
+
display_simple_list = lambda do |list, cols|
|
|
12
|
+
max_length = list.map(&:length).max
|
|
13
|
+
display_set = []
|
|
14
|
+
rows = (list.length / cols.to_f).ceil
|
|
15
|
+
row_idx = 0
|
|
16
|
+
max_rows = rows - 1
|
|
17
|
+
list.length.times do |i|
|
|
18
|
+
display_set[row_idx] ||= []
|
|
19
|
+
display_set[row_idx] << list[i]
|
|
20
|
+
row_idx += 1
|
|
21
|
+
row_idx = 0 if row_idx > max_rows
|
|
22
|
+
end
|
|
23
|
+
display_set.map { |row| row.map { |z| z.ljust(max_length) }.join(' ') }.join("\n")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
display_detailed_zone_list = lambda do |list|
|
|
27
|
+
max_shortcut_length = list.map { |zone| (zone[:shortcut] || '').length }.max
|
|
28
|
+
formatter = "%-#{max_shortcut_length}s %3s %s"
|
|
29
|
+
final_string = ''
|
|
30
|
+
final_string << format(formatter, 'Shortcut', 'Act', 'Zone') + "\n"
|
|
31
|
+
final_string << list.map { |zone| format(formatter, zone[:shortcut], zone[:min_act], zone[:slug]) }.join("\n")
|
|
32
|
+
final_string
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if args.empty? || params[:list]
|
|
36
|
+
Rbcli.log.info 'Shortcuts:'
|
|
37
|
+
Rbcli.log.info display_simple_list.call(c.list_shortcuts.keys, 5)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if params[:list]
|
|
41
|
+
Rbcli.log.info ''
|
|
42
|
+
Rbcli.log.info 'Zones:'
|
|
43
|
+
Rbcli.log.info display_detailed_zone_list.call(c.list_zones)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Rbcli.exit(0) if args.empty? || params[:list]
|
|
47
|
+
|
|
48
|
+
status = c.zone_to(args.first, force_soft_reqs: params[:force], enforce_min_act: !params[:force])
|
|
49
|
+
case status
|
|
50
|
+
when :no_zone
|
|
51
|
+
Rbcli.log.warn "Could not zone to #{args.first}: Specified spawn point does not exist"
|
|
52
|
+
Rbcli.log.info 'Did you mean one of these?'
|
|
53
|
+
possible_zones = c.list_zones.select { |zone| zone[:slug].include?(args.first) || !zone[:shortcut].nil? && zone[:shortcut].include?(args.first) }
|
|
54
|
+
Rbcli.log.info display_detailed_zone_list.call(possible_zones, 5)
|
|
55
|
+
when :failed_act_check
|
|
56
|
+
Rbcli.log.warn "Could not zone to #{args.first.colorize(:red)}: The player is in the wrong act. Use --(f)orce to override."
|
|
57
|
+
when :failed_soft_reqs
|
|
58
|
+
Rbcli.log.warn "Could not zone to #{args.first.colorize(:red)}: Soft requirements not met. Use --(f)orce to apply the required changes."
|
|
59
|
+
when :failed_hard_reqs
|
|
60
|
+
Rbcli.log.error "Could not zone to #{args.first.colorize(:red)}: Hard requirements not met. Zoning here would cause in-game errors."
|
|
61
|
+
when :success
|
|
62
|
+
s.direct_backup
|
|
63
|
+
s.save_to_dat
|
|
64
|
+
Rbcli.log.info "Zoned to #{args.first.colorize(:green)}"
|
|
65
|
+
else
|
|
66
|
+
raise "Unknown status: #{status}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
Rbcli.command 'mkzone' do
|
|
72
|
+
description 'Adds a new spawn point to the library'
|
|
73
|
+
usage '<slug>'
|
|
74
|
+
parameter :slug, 'The slug of the zone to add', type: :string
|
|
75
|
+
parameter :act, 'Override default act detection', type: :integer
|
|
76
|
+
parameter :shortcut, 'Provide a shorter slug as a shortcut for the zone', short: 'o', type: :string
|
|
77
|
+
parameter :force, 'Force overwrite of existing zone', type: :bool, default: false
|
|
78
|
+
action do |opts, params, args, config, env|
|
|
79
|
+
if params[:slug].nil?
|
|
80
|
+
Rbcli.log.error 'Must provide a zone slug'
|
|
81
|
+
next
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
s = Silkedit::Savegame::SaveFile.new(:silksong, opts[:savenum])
|
|
85
|
+
s.load_from_dat
|
|
86
|
+
c = Silkedit::Cheat::Engine.new(s.data)
|
|
87
|
+
|
|
88
|
+
status = c.save_current_zone(params[:slug], params[:shortcut], params[:act], overwrite: params[:force])
|
|
89
|
+
|
|
90
|
+
case status
|
|
91
|
+
when :badname
|
|
92
|
+
Rbcli.log.error 'Invalid zone name. Zones must be formatted as: region.target'
|
|
93
|
+
when :badact
|
|
94
|
+
Rbcli.log.error 'Invalid act number. Act must be between 1 and 3, or leave blank for autodetection.'
|
|
95
|
+
when :badshortcut
|
|
96
|
+
Rbcli.log.error 'Invalid shortcut. Shortcuts must not have a period (.) in them.'
|
|
97
|
+
when :success
|
|
98
|
+
Rbcli.log.info "Added #{params[:slug]} to zonelist."
|
|
99
|
+
else
|
|
100
|
+
Rbcli.log.error "Duplicate zone found: #{status}. Use --(f)orce to overwrite."
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Rbcli::Configurate.config do
|
|
2
|
+
##### Config (Optional) #####
|
|
3
|
+
# The built-in config will automatically pull in a config file to a hash and vice versa
|
|
4
|
+
# It can either be used immutably (as user-defined configuration) and/or to store application state
|
|
5
|
+
#
|
|
6
|
+
# file: <string> or <array> (Required) Provide either a specific config file location or a hierarchy to search. If creating a :null type of config this can be omitted.
|
|
7
|
+
# type: (:yaml|:json|:ini|:toml|:null) (Optional) Select which backend/file format to use. If the file has an associated extension (i.e. '.yaml') then this can be omitted.
|
|
8
|
+
# schema_file: <string> (Optional) The file location of a JSON Schema (https://json-schema.org). If provided, the config will automatically be validated. (default: nil)
|
|
9
|
+
# schema_hash: <string> (Optional) If you'd like to provide a JSON schema hash directly instead, do it here. May not use `schema_hash` and `schema_file` together. (default: nil)
|
|
10
|
+
# save_on_exit: (true|false) (Optional) Save changes to the config file on exit (default: false)
|
|
11
|
+
# create_if_not_exists: (true|false) (Optional) Create the file using default values if it is not found on the system (default: false)
|
|
12
|
+
# suppress_errors: (true|false) (Optional) If set to false, the application will halt on any errors in loading the config. If set to true, defaults will be provided (default: true)
|
|
13
|
+
# banner: <string> (Optional) Define a banner to be placed at the top of the config file on disk. Note that it will only be written to backends that support comments
|
|
14
|
+
# defaults: <hash> (Optional) Defaults set here will be provided to your application if any values are missing in the config.
|
|
15
|
+
# They will also be used to create new config files when the flag `create_if_not_exists` is set to true.
|
|
16
|
+
# skeleton: <string> (Optional) If a skeleton is provided, it will be used as the config source when creating new config files on disk instead of the defaults. (default: nil)`
|
|
17
|
+
# Please provide the text exactly as you want the user to see it in the config file (plus the banner if provided).
|
|
18
|
+
file [File.join(Silkedit::LIBDIR, 'config', 'silkedit.yaml')]
|
|
19
|
+
type :yaml
|
|
20
|
+
# schema_file nil
|
|
21
|
+
# schema_hash nil
|
|
22
|
+
save_on_exit false
|
|
23
|
+
create_if_not_exists false
|
|
24
|
+
suppress_errors true
|
|
25
|
+
# banner nil
|
|
26
|
+
# defaults({ editor_command: "vi '%FILE%'", permasaves: {} })
|
|
27
|
+
# skeleton "eJzT1dXlSsvPt1JISiziAhFWSYlVAD1hBjs=".decompress
|
|
28
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Rbcli::Configurate.envvars do
|
|
2
|
+
##### Environment Variable Parsing (Optional) #####
|
|
3
|
+
# The envvars module can pull in all environment variables with a given
|
|
4
|
+
# prefix and organize them into a hash structure based on name.
|
|
5
|
+
# It will also parse the string values and convert them to the proper type (Integer, Boolean, etc)
|
|
6
|
+
# Any values set here will be treated as defaults and made available when a variable is missing
|
|
7
|
+
#
|
|
8
|
+
# For example, these two environment variables:
|
|
9
|
+
# SILKEDIT_TERM_HEIGHT=40
|
|
10
|
+
# SILKEDIT_TERM_WIDTH=120
|
|
11
|
+
# Would be declared here as:
|
|
12
|
+
# prefix 'SILKEDIT'
|
|
13
|
+
# envvar 'TERM_HEIGHT', 40
|
|
14
|
+
# envvar 'TERM_WIDTH', 120
|
|
15
|
+
# And get loaded into the env hash as:
|
|
16
|
+
# { term: { height: 40, width: 120 } }
|
|
17
|
+
#
|
|
18
|
+
# If the prefix is unset or equal to nil, the environment variables specified here will
|
|
19
|
+
# be loaded without one.
|
|
20
|
+
prefix 'SILKEDIT'
|
|
21
|
+
envvar 'SAVENUM', nil
|
|
22
|
+
envvar 'DEVELOPMENT', false
|
|
23
|
+
end
|
data/lib/config/hooks.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Rbcli::Configurate.hooks do
|
|
2
|
+
##### Hooks (Optional) #####
|
|
3
|
+
# These hooks are scheduled on the Rbcli execution engine to run
|
|
4
|
+
# Pre- and Post- the command specified. They are executed after
|
|
5
|
+
# everything else has been initialized, so the runtime configuration
|
|
6
|
+
# values are all made available, as they will appear to the command.
|
|
7
|
+
#
|
|
8
|
+
# These are good for parsing and/or doing transformations on the provided
|
|
9
|
+
# configuration before passing them to the command, and for cleaning
|
|
10
|
+
# up your environment afterwards.
|
|
11
|
+
pre_execute do |opts, params, args, config, env|
|
|
12
|
+
opts[:savenum] = env[:savenum] if opts[:savenum].nil? && !env[:savenum].nil?
|
|
13
|
+
|
|
14
|
+
if !opts[:savenum].is_a?(Integer) || opts[:savenum] < 1 || opts[:savenum] > 4
|
|
15
|
+
Rbcli.log.fatal 'A savegame index between 1-4 must be specified either via the command line (-s #) or environment variable (SILKEDIT_SAVENUM=#). See help (-h) for details.', exit_status: 24
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# post_execute do |opts, params, args, config, env|
|
|
20
|
+
# Rbcli.log.info "I'm done running the command!"
|
|
21
|
+
# end
|
|
22
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Rbcli::Configurate.logger do
|
|
2
|
+
##### Logger (Optional) #####
|
|
3
|
+
# The Rbcli logger is a wrapper around the standard Ruby `Logger` library
|
|
4
|
+
# It is recommended that - unless you want to use specialized output libraries (such as ncurses) - that all
|
|
5
|
+
# of your application output is directed through the logger. This will allow for easy formatting and redirection
|
|
6
|
+
# no matter how your application is run.
|
|
7
|
+
#
|
|
8
|
+
# Valid targets are: :stdout, :stderr, "/path/to/a/file", or an IO or StringIO object (Default: :stdout)
|
|
9
|
+
# Valid levels are: :debug, :info, :warn, :error, :fatal, :unknown, :any (Default: :info)
|
|
10
|
+
# Valid formats are: :display, :simple, :full, :ruby, :json, :apache, :lolcat (Default: :display)
|
|
11
|
+
#
|
|
12
|
+
# The first three formats are designed to cover most use cases:
|
|
13
|
+
# display: For display on a terminal, with user interaction
|
|
14
|
+
# simple: For display on a terminal, for a developer
|
|
15
|
+
# full: For logging to a file, or using log collection software
|
|
16
|
+
# The next three are for specialized integrations in case you already have log collection configured:
|
|
17
|
+
# ruby: Default ruby logger format
|
|
18
|
+
# json: Each line is a JSON object
|
|
19
|
+
# apache: Follows the standard Apache log format
|
|
20
|
+
# As for :lolcat... if you can't guess what it does then give it a shot
|
|
21
|
+
logger target: :stdout, level: :info, format: :display
|
|
22
|
+
# Custom formats can also be defined here.
|
|
23
|
+
# Declaring a format here will not switch to it. However, if
|
|
24
|
+
# the `format` keyword is used without providing a Proc, it will switch
|
|
25
|
+
# to that format.
|
|
26
|
+
#
|
|
27
|
+
# Format switch: format :json
|
|
28
|
+
# Format definition: format :foo, Proc.new { |severity, datetime, progname, msg| "Foo! " + msg }
|
|
29
|
+
#
|
|
30
|
+
# You can also switch formats mid-execution by calling this method on
|
|
31
|
+
# the logger object itself.
|
|
32
|
+
#
|
|
33
|
+
# Rbcli.log.format :json
|
|
34
|
+
#
|
|
35
|
+
# format :foo, Proc.new { |severity, datetime, progname, msg| "Foo! " + msg }
|
|
36
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Rbcli::Configurate.cli do
|
|
2
|
+
##### Core Configuration (Required) #####
|
|
3
|
+
# appname (Optional) - Defaults to the name of the executable
|
|
4
|
+
# author (Optional) - A name or array of names
|
|
5
|
+
# email (Optional) - An email for users to contact
|
|
6
|
+
# version (Optional) - major.minor.patch notation, required if using update checks
|
|
7
|
+
# copyright_year (Optional) - Self explanatory
|
|
8
|
+
# compatibility (Optional) - Array of Operating Systems, devices, or other targets (For example: %w[MacOS Linux Ubuntu Windows Raspberry\ Pi]
|
|
9
|
+
# license (Optional) - Convention is to use an identifier from here: https://spdx.org/licenses/
|
|
10
|
+
# helptext (Optional) - Text that gets shown with --help or -h
|
|
11
|
+
appname nil
|
|
12
|
+
author ['Andrew Khoury']
|
|
13
|
+
email nil
|
|
14
|
+
version Silkedit::VERSION
|
|
15
|
+
copyright_year 2025
|
|
16
|
+
compatibility %w[MacOS Linux]
|
|
17
|
+
license 'GPL-3.0'
|
|
18
|
+
helptext 'This is a tool to quickly and easily edit savefiles for SilkSong.'
|
|
19
|
+
##### CLI Options (Optional) #####
|
|
20
|
+
# These appear to commands as `opts`.
|
|
21
|
+
# Format:
|
|
22
|
+
# opt :name, "Description"[, optional arguments ]
|
|
23
|
+
# Optional Arguments:
|
|
24
|
+
# long: Specify the long form (--long) version of an argument. (Default: same as the name)
|
|
25
|
+
# short: Specify the short form (-s) version of an argument. (Default: first letter of the name)
|
|
26
|
+
# type: Specify the type. Valid options are :boolean, :float, :integer, :string, :io, :date. (Default: :boolean)
|
|
27
|
+
# If the plural form of any of the above are used (i.e. ':strings') then the user can provide a comma-delimited list on the command line (--param=foo,bar)
|
|
28
|
+
# required: If set to true, requires that this option is provided by the user. (Default: false)
|
|
29
|
+
# multi: If set to true, allows the option to be provided multiple times (--param --param, or in short form, -pp). (Default: false)
|
|
30
|
+
# When using this with a :boolean type, rather than returning `true` or `false`, it will return a count of the number of times the parameter was passed.
|
|
31
|
+
# permitted: If set to an array, restricts input to the values within that array. (Default: nil (no restrictions))
|
|
32
|
+
# opt :verbose, "Twice or more enables very-verbose output", multi: true
|
|
33
|
+
opt :savenum, "A number from 1-4, indicating which game save you'd like to address", short: 's', type: :integer
|
|
34
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Rbcli::Configurate.updatechecker do
|
|
2
|
+
##### Update Check (Optional) #####
|
|
3
|
+
# The application can warn users when a new version is released
|
|
4
|
+
# Checks can be done either by rubygems or by a Github repo
|
|
5
|
+
# Private servers for Github (enterprise) are supported
|
|
6
|
+
#
|
|
7
|
+
# Setting force_update to true will halt execution until it is updated
|
|
8
|
+
#
|
|
9
|
+
# For Github, an access_token is required for private repos. See: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
|
|
10
|
+
# gem 'silkedit', force_update: false, message: 'Please run `gem update silkedit` to upgrade to the latest version.'
|
|
11
|
+
# github 'repo/name', access_token: nil, enterprise_hostname: nil, force_update: false, message: 'Please download the latest version from Github'
|
|
12
|
+
end
|