diff --git a/.github/workflows/rspec_tests.yml b/.github/workflows/rspec_tests.yml index 199615df9..8add254ba 100644 --- a/.github/workflows/rspec_tests.yml +++ b/.github/workflows/rspec_tests.yml @@ -29,5 +29,12 @@ jobs: version: 1.0 - name: Run type data migrations to create gameobj-data.xml run: bin/migrate + - name: Upload gameobj-data.xml artifact + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 + with: + name: gameobj-data-ruby-${{ matrix.ruby }} + path: dist/gameobj-data.xml + retention-days: 1 + overwrite: true - name: Run RSpec tests run: bundle exec rspec diff --git a/lib/lich/gameobj.rb b/lib/lich/gameobj.rb index e0eb7c06d..8fee21de4 100644 --- a/lib/lich/gameobj.rb +++ b/lib/lich/gameobj.rb @@ -36,7 +36,8 @@ class GameObj attr_reader :id attr_accessor :noun, :name, :before_name, :after_name - def initialize(id, noun, name, before=nil, after=nil) + + def initialize(id, noun, name, before = nil, after = nil) @id = id @noun = noun @noun = 'lapis' if @noun == 'lapis lazuli' @@ -46,6 +47,7 @@ def initialize(id, noun, name, before=nil, after=nil) @before_name = before @after_name = after end + def type GameObj.load_data if @@type_data.empty? list = @@type_data.keys.find_all { |t| (@name =~ @@type_data[t][:name] or @noun =~ @@type_data[t][:noun]) and (@@type_data[t][:exclude].nil? or @name !~ @@type_data[t][:exclude]) } @@ -55,6 +57,7 @@ def type list.join(',') end end + def sellable GameObj.load_data if @@sellable_data.empty? list = @@sellable_data.keys.find_all { |t| (@name =~ @@sellable_data[t][:name] or @noun =~ @@sellable_data[t][:noun]) and (@@sellable_data[t][:exclude].nil? or @name !~ @@sellable_data[t][:exclude]) } @@ -64,17 +67,19 @@ def sellable list.join(',') end end + def status if @@npc_status.keys.include?(@id) @@npc_status[@id] elsif @@pc_status.keys.include?(@id) @@pc_status[@id] - elsif @@loot.find { |obj| obj.id == @id } or @@inv.find { |obj| obj.id == @id } or @@room_desc.find { |obj| obj.id == @id } or @@fam_loot.find { |obj| obj.id == @id } or @@fam_npcs.find { |obj| obj.id == @id } or @@fam_pcs.find { |obj| obj.id == @id } or @@fam_room_desc.find { |obj| obj.id == @id } or (@@right_hand.id == @id) or (@@left_hand.id == @id) or @@contents.values.find { |list| list.find { |obj| obj.id == @id } } + elsif @@loot.find { |obj| obj.id == @id } or @@inv.find { |obj| obj.id == @id } or @@room_desc.find { |obj| obj.id == @id } or @@fam_loot.find { |obj| obj.id == @id } or @@fam_npcs.find { |obj| obj.id == @id } or @@fam_pcs.find { |obj| obj.id == @id } or @@fam_room_desc.find { |obj| obj.id == @id } or (@@right_hand.id == @id) or (@@left_hand.id == @id) or @@contents.values.find { |list| list.find { |obj| obj.id == @id } } nil else 'gone' end end + def status=(val) if @@npcs.any? { |npc| npc.id == @id } @@npc_status[@id] = val @@ -84,52 +89,62 @@ def status=(val) nil end end + def to_s @noun end + def empty? false end + def contents @@contents[@id].dup end + def GameObj.[](val) if val.class == String if val =~ /^\-?[0-9]+$/ - obj = @@inv.find { |o| o.id == val } || @@loot.find { |o| o.id == val } || @@npcs.find { |o| o.id == val } || @@pcs.find { |o| o.id == val } || [ @@right_hand, @@left_hand ].find { |o| o.id == val } || @@room_desc.find { |o| o.id == val } + @@inv.find { |o| o.id == val } || @@loot.find { |o| o.id == val } || @@npcs.find { |o| o.id == val } || @@pcs.find { |o| o.id == val } || [@@right_hand, @@left_hand].find { |o| o.id == val } || @@room_desc.find { |o| o.id == val } elsif val.split(' ').length == 1 - obj = @@inv.find { |o| o.noun == val } || @@loot.find { |o| o.noun == val } || @@npcs.find { |o| o.noun == val } || @@pcs.find { |o| o.noun == val } || [ @@right_hand, @@left_hand ].find { |o| o.noun == val } || @@room_desc.find { |o| o.noun == val } + @@inv.find { |o| o.noun == val } || @@loot.find { |o| o.noun == val } || @@npcs.find { |o| o.noun == val } || @@pcs.find { |o| o.noun == val } || [@@right_hand, @@left_hand].find { |o| o.noun == val } || @@room_desc.find { |o| o.noun == val } else - obj = @@inv.find { |o| o.name == val } || @@loot.find { |o| o.name == val } || @@npcs.find { |o| o.name == val } || @@pcs.find { |o| o.name == val } || [ @@right_hand, @@left_hand ].find { |o| o.name == val } || @@room_desc.find { |o| o.name == val } || @@inv.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@loot.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@npcs.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@pcs.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || [ @@right_hand, @@left_hand ].find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@room_desc.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@inv.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || @@loot.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || @@npcs.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || @@pcs.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || [ @@right_hand, @@left_hand ].find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || @@room_desc.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } + @@inv.find { |o| o.name == val } || @@loot.find { |o| o.name == val } || @@npcs.find { |o| o.name == val } || @@pcs.find { |o| o.name == val } || [@@right_hand, @@left_hand].find { |o| o.name == val } || @@room_desc.find { |o| o.name == val } || @@inv.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@loot.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@npcs.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@pcs.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || [@@right_hand, @@left_hand].find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@room_desc.find { |o| o.name =~ /\b#{Regexp.escape(val.strip)}$/i } || @@inv.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || @@loot.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || @@npcs.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || @@pcs.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || [@@right_hand, @@left_hand].find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } || @@room_desc.find { |o| o.name =~ /\b#{Regexp.escape(val).sub(' ', ' .*')}$/i } end elsif val.class == Regexp - obj = @@inv.find { |o| o.name =~ val } || @@loot.find { |o| o.name =~ val } || @@npcs.find { |o| o.name =~ val } || @@pcs.find { |o| o.name =~ val } || [ @@right_hand, @@left_hand ].find { |o| o.name =~ val } || @@room_desc.find { |o| o.name =~ val } + @@inv.find { |o| o.name =~ val } || @@loot.find { |o| o.name =~ val } || @@npcs.find { |o| o.name =~ val } || @@pcs.find { |o| o.name =~ val } || [@@right_hand, @@left_hand].find { |o| o.name =~ val } || @@room_desc.find { |o| o.name =~ val } end end + def GameObj @noun end + def full_name "#{@before_name}#{' ' unless @before_name.nil? or @before_name.empty?}#{name}#{' ' unless @after_name.nil? or @after_name.empty?}#{@after_name}" end - def GameObj.new_npc(id, noun, name, status=nil) + + def GameObj.new_npc(id, noun, name, status = nil) obj = GameObj.new(id, noun, name) @@npcs.push(obj) @@npc_status[id] = status obj end + def GameObj.new_loot(id, noun, name) obj = GameObj.new(id, noun, name) @@loot.push(obj) obj end - def GameObj.new_pc(id, noun, name, status=nil) + + def GameObj.new_pc(id, noun, name, status = nil) obj = GameObj.new(id, noun, name) @@pcs.push(obj) @@pc_status[id] = status obj end - def GameObj.new_inv(id, noun, name, container=nil, before=nil, after=nil) + + def GameObj.new_inv(id, noun, name, container = nil, before = nil, after = nil) obj = GameObj.new(id, noun, name, before, after) if container @@contents[container].push(obj) @@ -138,72 +153,91 @@ def GameObj.new_inv(id, noun, name, container=nil, before=nil, after=nil) end obj end + def GameObj.new_room_desc(id, noun, name) obj = GameObj.new(id, noun, name) @@room_desc.push(obj) obj end + def GameObj.new_fam_room_desc(id, noun, name) obj = GameObj.new(id, noun, name) @@fam_room_desc.push(obj) obj end + def GameObj.new_fam_loot(id, noun, name) obj = GameObj.new(id, noun, name) @@fam_loot.push(obj) obj end + def GameObj.new_fam_npc(id, noun, name) obj = GameObj.new(id, noun, name) @@fam_npcs.push(obj) obj end + def GameObj.new_fam_pc(id, noun, name) obj = GameObj.new(id, noun, name) @@fam_pcs.push(obj) obj end + def GameObj.new_right_hand(id, noun, name) @@right_hand = GameObj.new(id, noun, name) end + def GameObj.right_hand @@right_hand.dup end + def GameObj.new_left_hand(id, noun, name) @@left_hand = GameObj.new(id, noun, name) end + def GameObj.left_hand @@left_hand.dup end + def GameObj.clear_loot @@loot.clear end + def GameObj.clear_npcs @@npcs.clear @@npc_status.clear end + def GameObj.clear_pcs @@pcs.clear @@pc_status.clear end + def GameObj.clear_inv @@inv.clear end + def GameObj.clear_room_desc @@room_desc.clear end + def GameObj.clear_fam_room_desc @@fam_room_desc.clear end + def GameObj.clear_fam_loot @@fam_loot.clear end + def GameObj.clear_fam_npcs @@fam_npcs.clear end + def GameObj.clear_fam_pcs @@fam_pcs.clear end + def GameObj.npcs if @@npcs.empty? nil @@ -211,6 +245,7 @@ def GameObj.npcs @@npcs.dup end end + def GameObj.loot if @@loot.empty? nil @@ -218,6 +253,7 @@ def GameObj.loot @@loot.dup end end + def GameObj.pcs if @@pcs.empty? nil @@ -225,6 +261,7 @@ def GameObj.pcs @@pcs.dup end end + def GameObj.inv if @@inv.empty? nil @@ -232,6 +269,7 @@ def GameObj.inv @@inv.dup end end + def GameObj.room_desc if @@room_desc.empty? nil @@ -239,6 +277,7 @@ def GameObj.room_desc @@room_desc.dup end end + def GameObj.fam_room_desc if @@fam_room_desc.empty? nil @@ -246,6 +285,7 @@ def GameObj.fam_room_desc @@fam_room_desc.dup end end + def GameObj.fam_loot if @@fam_loot.empty? nil @@ -253,6 +293,7 @@ def GameObj.fam_loot @@fam_loot.dup end end + def GameObj.fam_npcs if @@fam_npcs.empty? nil @@ -260,6 +301,7 @@ def GameObj.fam_npcs @@fam_npcs.dup end end + def GameObj.fam_pcs if @@fam_pcs.empty? nil @@ -267,12 +309,15 @@ def GameObj.fam_pcs @@fam_pcs.dup end end + def GameObj.clear_container(container_id) @@contents[container_id] = Array.new end + def GameObj.delete_container(container_id) @@contents.delete(container_id) end + def GameObj.dead dead_list = Array.new for obj in @@npcs @@ -281,10 +326,12 @@ def GameObj.dead return nil if dead_list.empty? return dead_list end + def GameObj.containers @@contents.dup end - def GameObj.load_data(filename=nil) + + def GameObj.load_data(filename = nil) if $SAFE == 0 if filename.nil? if File.exist?("#{DATA_DIR}/gameobj-data.xml") @@ -302,7 +349,7 @@ def GameObj.load_data(filename=nil) File.open(filename) { |file| doc = REXML::Document.new(file.read) doc.elements.each('data/type') { |e| - if type = e.attributes['name'] + if (type = e.attributes['name']) @@type_data[type] = Hash.new @@type_data[type][:name] = Regexp.new(e.elements['name'].text) unless e.elements['name'].text.nil? or e.elements['name'].text.empty? @@type_data[type][:noun] = Regexp.new(e.elements['noun'].text) unless e.elements['noun'].text.nil? or e.elements['noun'].text.empty? @@ -310,7 +357,7 @@ def GameObj.load_data(filename=nil) end } doc.elements.each('data/sellable') { |e| - if sellable = e.attributes['name'] + if (sellable = e.attributes['name']) @@sellable_data[sellable] = Hash.new @@sellable_data[sellable][:name] = Regexp.new(e.elements['name'].text) unless e.elements['name'].text.nil? or e.elements['name'].text.empty? @@sellable_data[sellable][:noun] = Regexp.new(e.elements['noun'].text) unless e.elements['noun'].text.nil? or e.elements['noun'].text.empty? @@ -336,9 +383,11 @@ def GameObj.load_data(filename=nil) @@elevated_load.call end end + def GameObj.type_data @@type_data end + def GameObj.sellable_data @@sellable_data end diff --git a/lib/migration.rb b/lib/migration.rb index f1feee695..4021a5c3c 100644 --- a/lib/migration.rb +++ b/lib/migration.rb @@ -1 +1 @@ -Dir[File.join(__dir__, "migration", "**", "*.rb")].each do |file| require(file) end \ No newline at end of file +Dir[File.join(__dir__, "migration", "**", "*.rb")].each do |file| require(file) end diff --git a/lib/migration/change-set.rb b/lib/migration/change-set.rb index e71c7ef23..d850fc457 100644 --- a/lib/migration/change-set.rb +++ b/lib/migration/change-set.rb @@ -1,37 +1,51 @@ require "pathname" module Migration - class PrettyError < Exception + class PrettyError < StandardError def initialize(changeset, msg) super <<~ERROR \n\t#{changeset.file.split("../").last} >> #{changeset.table.log_name} #{msg} ERROR end end + class KeyError < PrettyError; end class RuleError < PrettyError; end + ## ## this is execution instance for ## evaluating a new set of changes ## to be applied to a table ## class ChangeSet - def self.run(table, file, &block) - changeset = ChangeSet.new(table, file) + def self.run(table, file, tables, &block) + changeset = ChangeSet.new(table, file, tables) changeset.instance_eval(&block) changeset end - attr_reader :table, :file, :inserts, :deletes, :creates - def initialize(table, file) + attr_reader :table, :file, :inserts, :deletes, :creates, :tables + + def initialize(table, file, tables) @table = table @file = file + @tables = tables # Add this line @inserts = {} @deletes = {} @creates = [] @table.pending << self end + # Add helper methods + def get_table(table_name) + @tables[Table.normalize_key(table_name)] + end + + def copy_rules_from(source_table_name, key) + source_table = get_table(source_table_name) + source_table.get_rules(key) + end + def will_create?(key) @creates.include?(key) end diff --git a/lib/migration/convert.rb b/lib/migration/convert.rb index 65862bf9e..e7a6a386f 100644 --- a/lib/migration/convert.rb +++ b/lib/migration/convert.rb @@ -1,17 +1,17 @@ module Migration module Convert - # (?:seasoned |grizzled |battle\-scarred |ancient |veteran )? + # (?:seasoned |grizzled |battle\-scarred |ancient |veteran )? def self.maybe_pattern_to_regex(maybes = nil, space: nil, required_match: nil) return %{} if maybes.nil? - #Migration.log(maybes, label: %i[maybes]) + # Migration.log(maybes, label: %i[maybes]) with_whitespace = maybes.map do |maybe| if space.eql?(:left) " " + maybe elsif space.eql?(:right) - maybe + " " + maybe + " " else maybe - end + end end.join("|") if required_match.nil? %{(?:#{with_whitespace})?} @@ -31,4 +31,4 @@ def self.to_safe_xml(str) str.gsub(%[&], %[&]) end end -end \ No newline at end of file +end diff --git a/lib/migration/migration.rb b/lib/migration/migration.rb index 8176b6393..f89d7c343 100644 --- a/lib/migration/migration.rb +++ b/lib/migration/migration.rb @@ -8,8 +8,9 @@ module Migration # creates a raw xml element that does not escape # html entities, so regexp can properly be serialized def self.raw_element(name, parent = nil) - Element.new(name, parent, context = {raw: :all, attribute_quote: :quote}) + Element.new(name, parent, { raw: :all, attribute_quote: :quote }) end + ## ## lookup from cwd ## @@ -25,19 +26,19 @@ def self.log(msg, label: %i[], color: nil) end def self.load_tables(tables) - Hash[tables.map do |table| + Hash[tables.map do |table| table = Table.from_yaml(table) [table.name, table] end] end def self.load_migrations(migrations, tables) - migrations.sort.map do |migration| - Migrator.new(migration, tables) + migrations.sort.map do |migration| + Migrator.new(migration, tables) end end - def self.to_xml(tables) + def self.to_xml(_tables) root = raw_element(%{data}) @tables.values.map(&:to_xml).each do |child| root.add_element(child) @@ -51,9 +52,9 @@ def self.run(**opts) @migrations = Migration.load_migrations(opts.fetch(:migrations), @tables) @migrations.each(&:build).each(&:validate).each(&:apply) asset = File.join(opts.fetch(:dist), "gameobj-data.xml") - Migration.log(%{writing #{asset}}, - label: :write, - color: :pink) + Migration.log(%{writing #{asset}}, + label: :write, + color: :pink) File.open(asset, %{w+}) do |file| file.write Migration.to_xml(@tables).to_s end diff --git a/lib/migration/migrator.rb b/lib/migration/migrator.rb index 6dfedd5a0..43a47f7c2 100644 --- a/lib/migration/migrator.rb +++ b/lib/migration/migrator.rb @@ -1,6 +1,7 @@ module Migration - class TableNotFound < Exception; end - class DuplicateTable < Exception; end + class TableNotFound < StandardError; end + class DuplicateTable < StandardError; end + ## ## loads a migration Ruby instance and executes it ## within a ChangeSet context, storing the result @@ -9,12 +10,14 @@ class DuplicateTable < Exception; end ## class Migrator attr_reader :file, :tables, :basename + def initialize(file, tables) @file = file @tables = tables @basename = File.basename(@file) @changesets = [] end + ## ## read the file into this binding ## @@ -35,33 +38,37 @@ def apply_creations() @changesets.each do |changeset| changeset.creates.each do |key| Migration.log(%[#{changeset.table.log_name} CREATE key "#{key}"], - label: %i[changeset], - color: :light_blue) + label: %i[changeset], + color: :light_blue) changeset.table.create_key(key) end end end def apply_insertions() - @changesets.each do |changeset| + @changesets.each do |changeset| changeset.inserts.each do |key, rules| rules.each do |rule| Migration.log(%[#{changeset.table.log_name} INSERT #{key} "#{rule}"], - label: %i[changeset], - color: :green) + label: %i[changeset], + color: :green) end changeset.table.insert(key, *rules) end end end + def get_table(table_name) + @tables[Table.normalize_key(table_name)] + end + def apply_deletions() - @changesets.each do |changeset| + @changesets.each do |changeset| changeset.deletes.each do |key, rules| rules.each do |rule| Migration.log(%[#{changeset.table.log_name} DELETE #{key} "#{rule}"], - label: %i[changeset], - color: :yellow) + label: %i[changeset], + color: :yellow) end changeset.table.delete(key, *rules) @@ -70,24 +77,24 @@ def apply_deletions() end def assert_table_exists(table_name) - table = @tables[Table.normalize_key(table_name)] or + @tables[Table.normalize_key(table_name)] or fail TableNotFound, Color.red("Table[:#{table_name}] does not exist") end def assert_table_does_not_exist(table_name) - table = @tables[Table.normalize_key(table_name)] and + @tables[Table.normalize_key(table_name)] and fail DuplicateTable, Color.red("Table[:#{table_name}] already exists") end def migrate(*table_names, &migration) table_names.each do |table_name| table = assert_table_exists(table_name) - @changesets << ChangeSet.run(table, @file, &migration) + @changesets << ChangeSet.run(table, @file, @tables, &migration) # Add @tables here end self end - def create_table(table_name, kind: 'type', keys:[]) + def create_table(table_name, kind: 'type', keys: []) assert_table_does_not_exist(table_name) normalized_name = Table.normalize_key(table_name) @tables[normalized_name] = Table.new( diff --git a/lib/migration/table.rb b/lib/migration/table.rb index 39ed432d4..98f9a2a5a 100644 --- a/lib/migration/table.rb +++ b/lib/migration/table.rb @@ -21,27 +21,37 @@ class Table # Empty Ruleset Error # def self.raise_empty_ruleset(table) - fail Exception, <<~ERROR + fail StandardError, <<~ERROR Table[#{table.name}] exported an empty RuleSet and that is not allowed ERROR end + # # Error for bad key validation # def self.raise_bad_rule_kind(table, key) - fail Exception, <<~ERROR + fail StandardError, <<~ERROR Key[#{key}] in Table[#{table.name}] not a valid Key allowed metadata keys: #{METADATA_KEYS} allowed game-obj.xml keys: #{GAMEOBJ_DATA_KEYS} ERROR end + ## ## normalizes a key to what gameobj-data format expects ## def self.normalize_key(key) key.to_s.downcase.to_sym end + + # + # get all rules for a key: + # + def get_rules(key) + @rules[Table.normalize_key(key)] || [] + end + # # validate that a ruleset only contains # whitelisted keys @@ -55,17 +65,17 @@ def self.validate_ruleset(table, ruleset) # # Table Attributes # - attr_reader :name, # the name of the table in gameob-data.xml - # - :rules, # the set of rules that will be applied - # on encoding the table to gameobj-data.xml - # - :pending, # you can mark a table pending - # and it will not compile - # + attr_reader :name, # the name of the table in gameob-data.xml + :rules, # the set of rules that will be applied + # on encoding the table to gameobj-data.xml + # + :pending, # you can mark a table pending + # and it will not compile + # :kind, # sellable | type :basename, # the basename of the table :log_name # name to appear in logs + ## ## reads a .yaml definition into memory ## so that migrations may be layered ontop @@ -84,10 +94,10 @@ def self.from_yaml(file) # output something useful # about how we are loading this data Migration.log(%{decoding #{log_name} from #{file}}, - label: %i[table], - color: :blue) + label: %i[table], + color: :blue) - rules = Hash[YAML.load_file(file).map do |(k,v)| + rules = Hash[YAML.load_file(file).map do |(k, v)| [Table.normalize_key(k), v] end] kind = rules.fetch(:kind, "type") @@ -100,25 +110,29 @@ def self.from_yaml(file) rules: rules ) end + # # check for existance of a key # def has_key?(key) !@rules[Table.normalize_key(key)].nil? end + # # check if a given key has a rule # def has_rule?(key, rule) @rules[Table.normalize_key(key)].include?(rule) end + # - # fetches the current matcher expression + # fetches the current matcher expression # from the table by key # def get(key, default = nil) @rules.fetch(Table.normalize_key(key), default) end + # # inserts a new rule into a table on # the appropriate key @@ -126,6 +140,7 @@ def get(key, default = nil) def insert(key, *rules) @rules[Table.normalize_key(key)] = [*@rules[Table.normalize_key(key)], *rules] end + # # deletes a rule from a table on a key # since we are doing migrations over time @@ -136,14 +151,16 @@ def delete(key, *rules) @rules[Table.normalize_key(key)].delete(rule) end end + # # creates a new key with an empty ruleset # def create_key(key) insert(key) end + # - # dumps the table key/ruleset pairs to + # dumps the table key/ruleset pairs to # a Map(Key, Regexp) that can be used # def to_regex() @@ -162,10 +179,11 @@ def to_regex() @rules.select do |kind| (%i[name prefix prefix_required] & [kind]).empty? end.each do |kind, ruleset| next if ruleset.empty? regex_map[kind] = Validate.regexp(self, kind, - Convert.ruleset_to_regex(ruleset)) + Convert.ruleset_to_regex(ruleset)) end regex_map end + # # compiles the table key/ruleset pairs to # an XML document @@ -180,7 +198,8 @@ def to_xml() element = Migration.raw_element(kind.to_s) xml.add_element(element) element.add_text( - Convert.to_safe_xml(pattern)) + Convert.to_safe_xml(pattern) + ) end ## return the created document return xml diff --git a/lib/migration/validate.rb b/lib/migration/validate.rb index fed0b73bb..46e9ab26a 100644 --- a/lib/migration/validate.rb +++ b/lib/migration/validate.rb @@ -1,5 +1,5 @@ module Migration - class ValidationError < Exception; end + class ValidationError < StandardError; end module Validate def self.regexp(table, key, body) @@ -7,7 +7,7 @@ def self.regexp(table, key, body) Regexp.new(body) rescue => err fail ValidationError, <<~ERROR - + Table[#{table.name}:#{key}] -> Error #{err.message} @@ -16,4 +16,4 @@ def self.regexp(table, key, body) body end end -end \ No newline at end of file +end diff --git a/lib/spec/factories.rb b/lib/spec/factories.rb index 3ffb37218..768f3aefd 100644 --- a/lib/spec/factories.rb +++ b/lib/spec/factories.rb @@ -5,7 +5,7 @@ def self.npc_from_name(npc_name) GameObj.new_npc("fake_id", npc_name.split.last, npc_name) end - def self.item_from_name(item_name, item_noun=item_name.split.last, after_name=nil) + def self.item_from_name(item_name, item_noun = item_name.split.last, after_name = nil) GameObj.new_loot("fake_item_id", item_noun, item_name).tap do |loot| loot.after_name = after_name if after_name end diff --git a/lib/util/color.rb b/lib/util/color.rb index 67f90a1bf..0b1e51bd3 100644 --- a/lib/util/color.rb +++ b/lib/util/color.rb @@ -27,4 +27,4 @@ def self.pink(str) def self.light_blue(str) colorize(str, 36) end -end \ No newline at end of file +end diff --git a/spec/gameobj-data/core_spec.rb b/spec/gameobj-data/core_spec.rb index fcf8448e3..9b8f21f20 100644 --- a/spec/gameobj-data/core_spec.rb +++ b/spec/gameobj-data/core_spec.rb @@ -40,6 +40,7 @@ "herb", "instrument", "jar", + "jarable", "jewelry", "junk", "lm tool", diff --git a/spec/gameobj-data/gem_spec.rb b/spec/gameobj-data/gem_spec.rb index c6e4aff6a..8089e0b60 100644 --- a/spec/gameobj-data/gem_spec.rb +++ b/spec/gameobj-data/gem_spec.rb @@ -107,14 +107,14 @@ %{yellow zircon}, ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end it "recognizes blue lapis lazuli as a gem" do lapis_obj = GameObjFactory.item_from_name("blue lapis lazuli", "lapis") - expect(lapis_obj.type).to eq "gem" + expect(lapis_obj.type).to include "gem" expect(lapis_obj.sellable).to eq "gemshop" end end @@ -198,7 +198,7 @@ %{yellow hyacinth}, ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end @@ -235,7 +235,7 @@ %{snowflake zircon}, ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end @@ -287,7 +287,7 @@ %{transparent spherine}, ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end @@ -386,7 +386,7 @@ %{yellow sunstone}, ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end @@ -416,7 +416,7 @@ %{vibrant hummingbird saewehna}, ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end @@ -426,7 +426,8 @@ describe "krag dwellers gems" do ["brilliant purple opal"].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" + expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end end @@ -451,7 +452,7 @@ %{yellow sphene}, ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end @@ -471,7 +472,7 @@ %{uncut star-of-tamzyrr diamond}, ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end @@ -513,8 +514,8 @@ %{yellow helmet shell}, ].each do |valuable| it "recognizes #{valuable} as a valuable" do - expect(GameObjFactory.item_from_name(valuable).type).to eq "valuable" - expect(GameObjFactory.item_from_name(valuable).sellable).to eq "gemshop" + expect(GameObjFactory.item_from_name(valuable).type).to include "valuable" + expect(GameObjFactory.item_from_name(valuable).sellable).to include "gemshop" end end end @@ -537,7 +538,7 @@ %[twisted iron spiral], ].each do |gem| it "recognizes #{gem} as a gem" do - expect(GameObjFactory.item_from_name(gem).type).to eq "gem" + expect(GameObjFactory.item_from_name(gem).type).to include "gem" expect(GameObjFactory.item_from_name(gem).sellable).to eq "gemshop" end end diff --git a/type_data/migrations/66_jarable.rb b/type_data/migrations/66_jarable.rb new file mode 100644 index 000000000..1892e2cdd --- /dev/null +++ b/type_data/migrations/66_jarable.rb @@ -0,0 +1,64 @@ +create_table "jarable", keys: [:name, :noun, :exclude] + +migrate "jarable" do + insert(:name, %{amethyst clam shell}) + insert(:name, %{angulate wentletrap shell}) + insert(:name, %{beige clam shell}) + insert(:name, %{black-spined conch shell}) + insert(:name, %{blue-banded coquina shell}) + insert(:name, %{bright noble pectin shell}) + insert(:name, %{blue periwinkle shell}) + insert(:name, %{candystick tellin shell}) + insert(:name, %{checkered chiton shell}) + insert(:name, %{crown conch shell}) + insert(:name, %{crown-of-Charl shell}) + insert(:name, %{dovesnail shell}) + insert(:name, %{egg cowrie shell}) + insert(:name, %{fluted limpet shell}) + insert(:name, %{golden cowrie shell}) + insert(:name, %{polished hornsnail shell}) + insert(:name, %{piece of iridescent mother-of-pearl}) + insert(:name, %{large chipped clam shell}) + insert(:name, %{large moonsnail shell}) + insert(:name, %{lavender nassa shell}) + insert(:name, %{leopard cowrie shell}) + insert(:name, %{lynx cowrie shell}) + insert(:name, %{marlin spike shell}) + insert(:name, %{multi-colored snail shell}) + insert(:name, %{opaque spiral shell}) + insert(:name, %{pearl nautilus shell}) + insert(:name, %{pink-banded coquina shell}) + insert(:name, %{pink clam shell}) + insert(:name, %{polished batwing chiton shell}) + insert(:name, %{polished black tegula shell}) + insert(:name, %{purple-cap cowrie shell}) + insert(:name, %{ruby-lined nassa shell}) + insert(:name, %{sea urchin shell}) + insert(:name, %{silvery clam shell}) + insert(:name, %{snake-head cowrie shell}) + insert(:name, %{snow cowrie shell}) + insert(:name, %{Solhaven Bay scallop shell}) + insert(:name, %{sparkling silvery conch shell}) + insert(:name, %{speckled conch shell}) + insert(:name, %{spiny siren's-comb shell}) + insert(:name, %{spiral turret shell}) + insert(:name, %{striated abalone shell}) + insert(:name, %{sundial shell}) + insert(:name, %{three-lined nassa shell}) + insert(:name, %{tiger cowrie shell}) + insert(:name, %{tiger-striped nautilus shell}) + insert(:name, %{translucent golden spiral shell}) + insert(:name, %{yellow-banded coquina shell}) + insert(:name, %{white clam shell}) + insert(:name, %{white gryphon's wing shell}) + + copy_rules_from("gem", :name).each do |gem_name| + insert(:name, gem_name) + end + copy_rules_from("gem", :noun).each do |gem_name| + insert(:noun, gem_name) + end + copy_rules_from("gem", :exclude).each do |gem_name| + insert(:exclude, gem_name) + end +end