diff --git a/.github/workflows/publish-jinx.yaml b/.github/workflows/publish-jinx.yaml new file mode 100644 index 000000000..b5327afd8 --- /dev/null +++ b/.github/workflows/publish-jinx.yaml @@ -0,0 +1,52 @@ +name: Publish - Jinx Updates +on: + workflow_dispatch: +# push: +# branches: +# - master +# paths: +# - 'scripts/**' + +permissions: + contents: write + +jobs: + publish-jinx: + if: "!contains(github.event.head_commit.message, 'Repo updates within last')" + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - name: Checkout configuration + uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Update JINX manifest + continue-on-error: true + run: | + wget --tries=5 --retry-connrefused --retry-on-host-error https://github.com/elanthia-online/jinxp/releases/download/v0.4.0/jinxp \ + && chmod +x jinxp \ + && ./jinxp -i scripts + sed -i 's|/assets/|/scripts/|g' dist/manifest.json + mv dist/manifest.json ./ + mv dist/headers ./ + + - name: Commit changes + continue-on-error: true + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add headers + git add manifest.json + if [ -z "$(git status --porcelain)" ]; then + echo "No changes to commit" + else + git commit -m "Repo updates within last 3 hours" + fi + + - name: Push changes + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: ${{ github.ref }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yaml similarity index 77% rename from .github/workflows/publish.yml rename to .github/workflows/publish.yaml index 285d41a0a..a4e5df19e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yaml @@ -1,4 +1,4 @@ -name: Publish Updates +name: Publish - Repository Updates on: push: branches: [ 'master' ] @@ -6,14 +6,19 @@ on: jobs: publish: runs-on: ubuntu-latest + env: + BUNDLE_WITHOUT: 'gtk:vscode:profanity' + strategy: + matrix: + ruby: ['4.0'] name: Publish Updates steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: '20' - - uses: ruby/setup-ruby@d5126b9b3579e429dd52e51e68624dda2e05be25 # v1.267.0 + - uses: ruby/setup-ruby@708024e6c902387ab41de36e1669e43b5ee7085e # v1.283.0 with: - ruby-version: '2.7' + ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Install xmllint uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # v1.6.0 diff --git a/.github/workflows/rspec_tests.yml b/.github/workflows/rspec_tests.yaml similarity index 84% rename from .github/workflows/rspec_tests.yml rename to .github/workflows/rspec_tests.yaml index 199615df9..be6ccb80b 100644 --- a/.github/workflows/rspec_tests.yml +++ b/.github/workflows/rspec_tests.yaml @@ -12,13 +12,15 @@ concurrency: jobs: test: runs-on: ubuntu-latest + env: + BUNDLE_WITHOUT: 'gtk:vscode:profanity' strategy: matrix: - ruby: ['2.7'] + ruby: ['4.0'] name: Run tests on Ruby ${{ matrix.ruby }} steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: ruby/setup-ruby@d5126b9b3579e429dd52e51e68624dda2e05be25 # v1.267.0 + - uses: ruby/setup-ruby@708024e6c902387ab41de36e1669e43b5ee7085e # v1.283.0 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true diff --git a/.github/workflows/rubocop_syntax_checker.yaml b/.github/workflows/rubocop_syntax_checker.yaml index ca4c8890c..59bbd6b47 100644 --- a/.github/workflows/rubocop_syntax_checker.yaml +++ b/.github/workflows/rubocop_syntax_checker.yaml @@ -14,12 +14,14 @@ on: jobs: rubocop: runs-on: ubuntu-latest + env: + BUNDLE_WITHOUT: 'gtk:vscode:profanity' strategy: matrix: - ruby: ['3.3'] + ruby: ['4.0'] name: Run Rubocop on Ruby ${{ matrix.ruby }} steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.2 with: fetch-depth: 0 @@ -31,7 +33,7 @@ jobs: **/*.lic **/*.rb - - uses: ruby/setup-ruby@d5126b9b3579e429dd52e51e68624dda2e05be25 # v1.267.0 + - uses: ruby/setup-ruby@708024e6c902387ab41de36e1669e43b5ee7085e # v1.283.0 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true diff --git a/.github/workflows/ruby_syntax_checker.yml b/.github/workflows/ruby_syntax_checker.yaml similarity index 78% rename from .github/workflows/ruby_syntax_checker.yml rename to .github/workflows/ruby_syntax_checker.yaml index c80be4d7f..0ddb8ba8a 100644 --- a/.github/workflows/ruby_syntax_checker.yml +++ b/.github/workflows/ruby_syntax_checker.yaml @@ -14,12 +14,14 @@ on: jobs: check_syntax: runs-on: ubuntu-latest + env: + BUNDLE_WITHOUT: 'gtk:vscode:profanity' strategy: matrix: - ruby: ['3.3'] + ruby: ['4.0'] name: Run tests on Ruby ${{ matrix.ruby }} steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.2 with: fetch-depth: 0 @@ -30,12 +32,12 @@ jobs: files: | **/*.lic **/*.rb - - - uses: ruby/setup-ruby@d5126b9b3579e429dd52e51e68624dda2e05be25 # v1.267.0 + + - uses: ruby/setup-ruby@708024e6c902387ab41de36e1669e43b5ee7085e # v1.283.0 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - + - name: Run Ruby syntax check on changed scripts run: | for file in ${{ steps.changed-files.outputs.all_changed_files }}; do diff --git a/.rubocop.yml b/.rubocop.yml index 003cb2be3..ff00ccfad 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,6 @@ AllCops: SuggestExtensions: false - TargetRubyVersion: 3.3 + TargetRubyVersion: 4.0 NewCops: disable Include: - '**/*.lic' @@ -27,6 +27,9 @@ Layout/HeredocIndentation: Layout/LineLength: Enabled: false +Lint/MissingSuper: + AllowedParentClasses: [Object, BaseObject, GameBase::Game] + Metrics/AbcSize: Enabled: false diff --git a/.ruby-version b/.ruby-version index a0891f563..0c89fc927 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.3.4 +4.0.0 \ No newline at end of file diff --git a/Gemfile b/Gemfile index e8829a235..0f16177e0 100644 --- a/Gemfile +++ b/Gemfile @@ -1,12 +1,93 @@ -return true if ENV['NETLIFY'] +=begin +When building Gemfile.lock file, please add additional platforms to the file via the following command: -source 'https://rubygems.org' +bundle lock \ + --add-platform aarch64-linux \ + --add-platform aarch64-linux-gnu \ + --add-platform aarch64-linux-musl \ + --add-platform arm-linux \ + --add-platform arm-linux-gnu \ + --add-platform arm-linux-musl \ + --add-platform arm64-darwin \ + --add-platform x64-mingw \ + --add-platform x64-mingw-ucrt \ + --add-platform x86-darwin \ + --add-platform x86-linux \ + --add-platform x86-linux-gnu \ + --add-platform x86-linux-musl \ + --add-platform x86-mingw \ + --add-platform x86-mingw-ucrt \ + --add-platform x86_64-darwin \ + --add-platform x86_64-linux \ + --add-platform x86_64-linux-gnu \ + --add-platform x86_64-linux-musl + +This ensures that the lock file can be used by all platforms that are able to support it. +=end + +source "https://rubygems.org" + +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } group :development do gem "rspec" + gem "rubocop" gem "guard" gem "guard-rspec" gem "webmock" gem "rack" - gem 'rubocop' +end + +group :vscode do + gem "rbs" + gem "prism" + gem "sorbet-runtime" + gem "ruby-lsp" +end + +group :gtk do + gem "gtk3" +end + +group :profanity do + gem "curses" +end + +gem "ascii_charts" +gem "base64" +gem "benchmark" +gem "concurrent-ruby" +gem "digest" +gem "drb" +gem "ffi" +gem "fiddle" +gem "fileutils" +gem "json" +gem "kramdown" +gem "logger" +gem "openssl" +gem "open-uri" +gem "os" +gem "ostruct" +gem "rake" +gem "redis" +gem "resolv" +gem "rexml" +gem "sequel" +gem "set" +gem "tempfile" +gem "terminal-table" +gem "time" +gem "tmpdir" +gem "tzinfo" +gem "tzinfo-data" +gem "webrick" +gem "win32ole", platforms: :windows +gem "yaml" +gem "zlib" + +if Gem.win_platform? + gem "sqlite3", platforms: :windows, force_ruby_platform: true +else + gem "sqlite3" end diff --git a/bin/tasks/migrate.rb b/bin/tasks/migrate.rb index 8b490ac1b..e5c5d81ad 100644 --- a/bin/tasks/migrate.rb +++ b/bin/tasks/migrate.rb @@ -7,5 +7,6 @@ ## Migration.run( migrations: Dir[Migration.cwd("type_data", "migrations", "**", "*.rb")], - tables: Dir[Migration.cwd("type_data", "tables", "**", "*.yaml")], - dist: Migration.cwd("dist")) \ No newline at end of file + tables: Dir[Migration.cwd("type_data", "tables", "**", "*.yaml")], + dist: Migration.cwd("dist") +) diff --git a/lib/lich/gameobj.rb b/lib/lich/gameobj.rb index e0eb7c06d..bb11b7867 100644 --- a/lib/lich/gameobj.rb +++ b/lib/lich/gameobj.rb @@ -7,7 +7,6 @@ def method_missing(*); end # Tell GameObj where to find the GameObj data XML file class GameObj - require 'pathname' DATA_DIR = Pathname.new('./dist').expand_path # should inform the developer where the data is # being loaded from @@ -31,30 +30,40 @@ class GameObj @@fam_pcs = Array.new @@fam_room_desc = Array.new @@type_data = Hash.new + @@type_cache = Hash.new @@sellable_data = Hash.new - @@elevated_load = proc { GameObj.load_data } attr_reader :id attr_accessor :noun, :name, :before_name, :after_name - def initialize(id, noun, name, before=nil, after=nil) - @id = id + + def initialize(id, noun, name, before = nil, after = nil) + @id = id.is_a?(Integer) ? id.to_s : id @noun = noun @noun = 'lapis' if @noun == 'lapis lazuli' @noun = 'hammer' if @noun == "Hammer of Kai" + @noun = 'ball' if @noun == "ball and chain" # DR item 'ball and chain' doesn't work. @noun = 'mother-of-pearl' if (@noun == 'pearl') and (@name =~ /mother\-of\-pearl/) @name = name @before_name = before @after_name = after end + def type GameObj.load_data if @@type_data.empty? + return @@type_cache[@name] if @@type_cache.key?(@name) 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]) } if list.empty? - nil + return @@type_cache[@name] = nil else - list.join(',') + return @@type_cache[@name] = list.join(',') end end + + def type?(type_to_check) + # handle nil types + return self.type.to_s.split(',').any?(type_to_check) + 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 +73,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 +95,75 @@ 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 } - 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 } + unless val.is_a?(String) || val.is_a?(Regexp) + respond "--- Lich: error: GameObj[] passed with #{val.class} #{val} via caller: #{caller[0]}" + respond "--- Lich: error: GameObj[] supports String or Regexp only" + Lich.log "--- Lich: error: GameObj[] passed with #{val.class} #{val} via caller: #{caller[0]}\n\t" + Lich.log "--- Lich: error: GameObj[] supports String or Regexp only\n\t" + if val.is_a?(Integer) + respond "--- Lich: error: GameObj[] converted Integer #{val} to String to continue" + val = val.to_s 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 } + return + end + end + if val.is_a?(String) + if val =~ /^\-?[0-9]+$/ # ID lookup + # excludes @@room_desc ID lookup due to minimal use case, but could be added in future if desired + @@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 } || @@contents.values.flatten.find { |o| o.id == val } + elsif val.split(' ').length == 1 # noun lookup + @@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 # name lookup + @@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 } + elsif val.is_a?(Regexp) # name only lookup when passed a Regexp + @@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 +172,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 +264,7 @@ def GameObj.npcs @@npcs.dup end end + def GameObj.loot if @@loot.empty? nil @@ -218,6 +272,7 @@ def GameObj.loot @@loot.dup end end + def GameObj.pcs if @@pcs.empty? nil @@ -225,6 +280,7 @@ def GameObj.pcs @@pcs.dup end end + def GameObj.inv if @@inv.empty? nil @@ -232,6 +288,7 @@ def GameObj.inv @@inv.dup end end + def GameObj.room_desc if @@room_desc.empty? nil @@ -239,6 +296,7 @@ def GameObj.room_desc @@room_desc.dup end end + def GameObj.fam_room_desc if @@fam_room_desc.empty? nil @@ -246,6 +304,7 @@ def GameObj.fam_room_desc @@fam_room_desc.dup end end + def GameObj.fam_loot if @@fam_loot.empty? nil @@ -253,6 +312,7 @@ def GameObj.fam_loot @@fam_loot.dup end end + def GameObj.fam_npcs if @@fam_npcs.empty? nil @@ -260,6 +320,7 @@ def GameObj.fam_npcs @@fam_npcs.dup end end + def GameObj.fam_pcs if @@fam_pcs.empty? nil @@ -267,78 +328,143 @@ 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.targets + a = Array.new + XMLData.current_target_ids.each { |id| + if (npc = @@npcs.find { |n| n.id == id }) + next if (npc.status =~ /dead|gone/i) + next if (npc.name =~ /^animated\b/i && npc.name !~ /^animated slush/i) + next if (npc.noun =~ /^(?:arm|appendage|claw|limb|pincer|tentacle)s?$|^(?:palpus|palpi)$/i && npc.name !~ /(?:amaranthine|ghostly|grizzled|ancient) kraken tentacle/i) + a.push(npc) + end + } + a + end + + def GameObj.hidden_targets + a = Array.new + XMLData.current_target_ids.each { |id| + unless @@npcs.find { |n| n.id == id } + a.push(id) + end + } + a + end + + def GameObj.target + return (@@npcs + @@pcs).find { |n| n.id == XMLData.current_target_id } + end + def GameObj.dead dead_list = Array.new for obj in @@npcs dead_list.push(obj) if obj.status == "dead" end return nil if dead_list.empty? + return dead_list end + def GameObj.containers @@contents.dup end - def GameObj.load_data(filename=nil) - if $SAFE == 0 - if filename.nil? - if File.exist?("#{DATA_DIR}/gameobj-data.xml") - filename = "#{DATA_DIR}/gameobj-data.xml" - elsif File.exist?("#{SCRIPT_DIR}/gameobj-data.xml") # deprecated - filename = "#{SCRIPT_DIR}/gameobj-data.xml" - else - filename = "#{DATA_DIR}/gameobj-data.xml" - end - end - if File.exist?(filename) - begin - @@type_data = Hash.new - @@sellable_data = Hash.new - File.open(filename) { |file| - doc = REXML::Document.new(file.read) - doc.elements.each('data/type') { |e| - 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? - @@type_data[type][:exclude] = Regexp.new(e.elements['exclude'].text) unless e.elements['exclude'].text.nil? or e.elements['exclude'].text.empty? - end - } - doc.elements.each('data/sellable') { |e| - 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? - @@sellable_data[sellable][:exclude] = Regexp.new(e.elements['exclude'].text) unless e.elements['exclude'].text.nil? or e.elements['exclude'].text.empty? - end - } + + def GameObj.reload(filename = nil) + GameObj.load_data(filename) + end + + def GameObj.merge_data(data, newData) + return newData unless data.is_a?(Regexp) + return Regexp.union(data, newData) + end + + def GameObj.load_data(filename = nil) + filename = File.join(DATA_DIR, 'gameobj-data.xml') if filename.nil? + if File.exist?(filename) + begin + @@type_data = Hash.new + @@sellable_data = Hash.new + @@type_cache = Hash.new + File.open(filename) { |file| + doc = REXML::Document.new(file.read) + doc.elements.each('data/type') { |e| + 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? + @@type_data[type][:exclude] = Regexp.new(e.elements['exclude'].text) unless e.elements['exclude'].text.nil? or e.elements['exclude'].text.empty? + end } - true - rescue - @@type_data = nil - @@sellable_data = nil - echo "error: GameObj.load_data: #{$!}" - respond $!.backtrace[0..1] - false - end - else + doc.elements.each('data/sellable') { |e| + 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? + @@sellable_data[sellable][:exclude] = Regexp.new(e.elements['exclude'].text) unless e.elements['exclude'].text.nil? or e.elements['exclude'].text.empty? + end + } + } + rescue @@type_data = nil @@sellable_data = nil - echo "error: GameObj.load_data: file does not exist: #{filename}" - false + echo "error: GameObj.load_data: #{$!}" + respond $!.backtrace[0..1] + return false end else - @@elevated_load.call + @@type_data = nil + @@sellable_data = nil + echo "error: GameObj.load_data: file does not exist: #{filename}" + return false + end + filename = File.join(DATA_DIR, 'gameobj-custom', 'gameobj-data.xml') + if (File.exist?(filename)) + begin + File.open(filename) { |file| + doc = REXML::Document.new(file.read) + doc.elements.each('data/type') { |e| + if (type = e.attributes['name']) + @@type_data[type] ||= Hash.new + @@type_data[type][:name] = GameObj.merge_data(@@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] = GameObj.merge_data(@@type_data[type][:noun], Regexp.new(e.elements['noun'].text)) unless e.elements['noun'].text.nil? or e.elements['noun'].text.empty? + @@type_data[type][:exclude] = GameObj.merge_data(@@type_data[type][:exclude], Regexp.new(e.elements['exclude'].text)) unless e.elements['exclude'].text.nil? or e.elements['exclude'].text.empty? + end + } + doc.elements.each('data/sellable') { |e| + if (sellable = e.attributes['name']) + @@sellable_data[sellable] ||= Hash.new + @@sellable_data[sellable][:name] = GameObj.merge_data(@@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] = GameObj.merge_data(@@sellable_data[sellable][:noun], Regexp.new(e.elements['noun'].text)) unless e.elements['noun'].text.nil? or e.elements['noun'].text.empty? + @@sellable_data[sellable][:exclude] = GameObj.merge_data(@@sellable_data[sellable][:exclude], Regexp.new(e.elements['exclude'].text)) unless e.elements['exclude'].text.nil? or e.elements['exclude'].text.empty? + end + } + } + rescue + echo "error: Custom GameObj.load_data: #{$!}" + respond $!.backtrace[0..1] + return false + end end + return true end + def GameObj.type_data @@type_data end + + def GameObj.type_cache + @@type_cache + end + def GameObj.sellable_data @@sellable_data end diff --git a/scripts/noop.lic b/scripts/noop.lic index 04c084739..484297dca 100644 --- a/scripts/noop.lic +++ b/scripts/noop.lic @@ -1,13 +1,13 @@ =begin - A simple script to allow for learning elanthia-online integration - with Github + CI environments. + A simple script to allow for learning elanthia-online integration + with Github + CI environments. - author: elanthia-online - game: Gemstone - tags: testing - version: 1.0 + author: elanthia-online + game: Gemstone + tags: testing + version: 1.0 - To help contribute: https://github.com/elanthia-online/scripts + To help contribute: https://github.com/elanthia-online/scripts =end exit