hytale 0.0.1 → 0.1.0

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +1315 -15
  4. data/exe/hytale +497 -0
  5. data/lib/hytale/client/assets.rb +207 -0
  6. data/lib/hytale/client/block_type.rb +169 -0
  7. data/lib/hytale/client/config.rb +98 -0
  8. data/lib/hytale/client/cosmetics.rb +95 -0
  9. data/lib/hytale/client/item_type.rb +248 -0
  10. data/lib/hytale/client/launcher_log/launcher_log_entry.rb +58 -0
  11. data/lib/hytale/client/launcher_log/launcher_log_session.rb +55 -0
  12. data/lib/hytale/client/launcher_log.rb +94 -0
  13. data/lib/hytale/client/locale.rb +234 -0
  14. data/lib/hytale/client/map/block.rb +135 -0
  15. data/lib/hytale/client/map/chunk.rb +693 -0
  16. data/lib/hytale/client/map/marker.rb +50 -0
  17. data/lib/hytale/client/map/region.rb +278 -0
  18. data/lib/hytale/client/map/renderer.rb +437 -0
  19. data/lib/hytale/client/map.rb +271 -0
  20. data/lib/hytale/client/memories.rb +59 -0
  21. data/lib/hytale/client/npc_memory.rb +39 -0
  22. data/lib/hytale/client/permissions.rb +52 -0
  23. data/lib/hytale/client/player/entity_stats.rb +46 -0
  24. data/lib/hytale/client/player/inventory.rb +46 -0
  25. data/lib/hytale/client/player/item.rb +102 -0
  26. data/lib/hytale/client/player/item_storage.rb +32 -0
  27. data/lib/hytale/client/player/player_memory.rb +29 -0
  28. data/lib/hytale/client/player/position.rb +12 -0
  29. data/lib/hytale/client/player/rotation.rb +11 -0
  30. data/lib/hytale/client/player/vector3.rb +12 -0
  31. data/lib/hytale/client/player.rb +99 -0
  32. data/lib/hytale/client/player_skin.rb +179 -0
  33. data/lib/hytale/client/prefab/palette_entry.rb +49 -0
  34. data/lib/hytale/client/prefab.rb +184 -0
  35. data/lib/hytale/client/process.rb +57 -0
  36. data/lib/hytale/client/save/backup.rb +43 -0
  37. data/lib/hytale/client/save/server_log.rb +42 -0
  38. data/lib/hytale/client/save.rb +157 -0
  39. data/lib/hytale/client/settings/audio_settings.rb +30 -0
  40. data/lib/hytale/client/settings/builder_tools_settings.rb +27 -0
  41. data/lib/hytale/client/settings/gameplay_settings.rb +23 -0
  42. data/lib/hytale/client/settings/input_bindings.rb +25 -0
  43. data/lib/hytale/client/settings/mouse_settings.rb +23 -0
  44. data/lib/hytale/client/settings/rendering_settings.rb +30 -0
  45. data/lib/hytale/client/settings.rb +81 -0
  46. data/lib/hytale/client/world/client_effects.rb +24 -0
  47. data/lib/hytale/client/world/death_settings.rb +22 -0
  48. data/lib/hytale/client/world.rb +88 -0
  49. data/lib/hytale/client.rb +142 -0
  50. data/lib/hytale/server/process.rb +8 -0
  51. data/lib/hytale/server.rb +6 -0
  52. data/lib/hytale/version.rb +1 -1
  53. data/lib/hytale.rb +37 -2
  54. metadata +117 -10
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class Settings
6
+ class AudioSettings
7
+ attr_reader :data
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def output_device = data["OutputDevice"]
14
+ def master_volume = data["MasterVolume"]
15
+ def output_mode = data["OutputMode"]
16
+
17
+ def music_volume = category_volumes["Music"]
18
+ def ambient_volume = category_volumes["Ambient"]
19
+ def sfx_volume = category_volumes["SFX"]
20
+ def ui_volume = category_volumes["UI"]
21
+
22
+ def category_volumes
23
+ data["CategoryVolumes"] || {}
24
+ end
25
+
26
+ def to_h = data
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class Settings
6
+ class BuilderToolsSettings
7
+ attr_reader :data
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def tool_reach_distance = data["ToolReachDistance"]
14
+ def brush_shape_rendering? = data["EnableBrushShapeRendering"]
15
+ def brush_opacity = data["BrushOpacity"]
16
+ def selection_opacity = data["SelectionOpacity"]
17
+ def display_legend? = data["DisplayLegend"]
18
+ def laser_pointer_color = data["LaserPointerColor"]
19
+ def flight_inertia = data["FlightInertia"]
20
+ def no_clip? = data["EnableNoClip"]
21
+ def fullbright? = data["FullbrightEnabled"]
22
+
23
+ def to_h = data
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class Settings
6
+ class GameplaySettings
7
+ attr_reader :data
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def camera_based_flying? = data["CameraBasedFlying"]
14
+ def camera_based_climbing? = data["CameraBasedClimbing"]
15
+ def auto_jump_obstacle? = data["AutoJumpObstacle"]
16
+ def utility_quick_swap? = data["EnableUtilityQuickSwap"]
17
+ def arachnophobia_mode? = data["EnableArachnophobiaMode"]
18
+
19
+ def to_h = data
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class Settings
6
+ class InputBindings
7
+ attr_reader :data
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def [](action)
14
+ data[action]
15
+ end
16
+
17
+ def actions
18
+ data.keys
19
+ end
20
+
21
+ def to_h = data
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class Settings
6
+ class MouseSettings
7
+ attr_reader :data
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def inverted? = data["MouseInverted"]
14
+ def x_speed = data["MouseXSpeed"]
15
+ def y_speed = data["MouseYSpeed"]
16
+ def sensitivity = [x_speed, y_speed]
17
+ def invert_scroll? = data["InvertMouseWheelScrollDirection"]
18
+
19
+ def to_h = data
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class Settings
6
+ class RenderingSettings
7
+ attr_reader :data
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def render_scale = data["RenderScale"]
14
+ def view_distance = data["ViewDistance"]
15
+ def lod = data["Lod"]
16
+ def anti_aliasing = data["AntiAliasing"]
17
+ def shadows = data["Shadows"]
18
+ def shading = data["Shading"]
19
+ def bloom = data["Bloom"]
20
+ def sunshaft? = data["UseSunshaft"]
21
+ def depth_of_field = data["DepthOfField"]
22
+ def water = data["Water"]
23
+ def foliage_fading? = data["UseFoliageFading"]
24
+ def particles = data["Particles"]
25
+
26
+ def to_h = data
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class Settings
6
+ attr_reader :data, :path
7
+
8
+ def initialize(data, path: nil)
9
+ @data = data
10
+ @path = path
11
+ end
12
+
13
+ # Display settings
14
+ def fullscreen? = data["Fullscreen"]
15
+ def maximized? = data["Maximized"]
16
+ def window_width = data["WindowWidth"]
17
+ def window_height = data["WindowHeight"]
18
+ def window_size = [window_width, window_height]
19
+ def vsync? = data["VSync"]
20
+ def fps_limit = data["FpsLimit"]
21
+ def unlimited_fps? = data["UnlimitedFps"]
22
+ def field_of_view = data["FieldOfView"]
23
+
24
+ # Rendering settings
25
+ def rendering
26
+ @rendering ||= RenderingSettings.new(data["RenderingSettings"] || {})
27
+ end
28
+
29
+ # Input settings
30
+ def input_bindings
31
+ @input_bindings ||= InputBindings.new(data["InputBindings"] || {})
32
+ end
33
+
34
+ def mouse_settings
35
+ @mouse_settings ||= MouseSettings.new(data["MouseSettings"] || {})
36
+ end
37
+
38
+ # Audio settings
39
+ def audio
40
+ @audio ||= AudioSettings.new(data["AudioSettings"] || {})
41
+ end
42
+
43
+ # Gameplay settings
44
+ def gameplay
45
+ @gameplay ||= GameplaySettings.new(data["GameplaySettings"] || {})
46
+ end
47
+
48
+ # Builder tools settings
49
+ def builder_tools
50
+ @builder_tools ||= BuilderToolsSettings.new(data["BuilderToolsSettings"] || {})
51
+ end
52
+
53
+ # UI preferences
54
+ def hide_hud? = data["HideHud"]
55
+ def hide_hotbar? = data["HideHotbar"]
56
+ def hide_compass? = data["HideCompass"]
57
+ def hide_chat? = data["HideChat"]
58
+ def diagnostic_mode? = data["DiagnosticMode"]
59
+ def display_combat_text? = data["DisplayCombatText"]
60
+ def sprint_fov_effect? = data["SprintFovEffect"]
61
+ def view_bobbing_effect? = data["ViewBobbingEffect"]
62
+ def camera_shake_effect? = data["CameraShakeEffect"]
63
+
64
+ def to_h
65
+ data
66
+ end
67
+
68
+ class << self
69
+ def load(path: Config.settings_path)
70
+ raise NotFoundError, "Settings file not found: #{path}" unless File.exist?(path)
71
+
72
+ json = File.read(path)
73
+ data = JSON.parse(json)
74
+ new(data, path: path)
75
+ rescue JSON::ParserError => e
76
+ raise ParseError, "Failed to parse settings: #{e.message}"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class World
6
+ class ClientEffects
7
+ attr_reader :data
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def sun_height_percent = data["SunHeightPercent"]
14
+ def sun_angle_degrees = data["SunAngleDegrees"]
15
+ def bloom_intensity = data["BloomIntensity"]
16
+ def bloom_power = data["BloomPower"]
17
+ def sun_intensity = data["SunIntensity"]
18
+ def sunshaft_intensity = data["SunshaftIntensity"]
19
+
20
+ def to_h = data
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class World
6
+ class DeathSettings
7
+ attr_reader :data
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def respawn_controller = data.dig("RespawnController", "Type")
14
+ def items_loss_mode = data["ItemsLossMode"]
15
+ def items_loss_percentage = data["ItemsAmountLossPercentage"]
16
+ def durability_loss_percentage = data["ItemsDurabilityLossPercentage"]
17
+
18
+ def to_h = data
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class World
6
+ attr_reader :data, :path
7
+
8
+ def initialize(data, path: nil)
9
+ @data = data
10
+ @path = path
11
+ end
12
+
13
+ def version = data["Version"]
14
+ def uuid = data.dig("UUID", "$binary")
15
+ def display_name = data["DisplayName"]
16
+ def seed = data["Seed"]
17
+
18
+ def world_gen
19
+ data["WorldGen"] || {}
20
+ end
21
+
22
+ def world_gen_type = world_gen["Type"]
23
+ def world_gen_name = world_gen["Name"]
24
+
25
+ def game_mode = data["GameMode"]
26
+ def ticking? = data["IsTicking"]
27
+ def block_ticking? = data["IsBlockTicking"]
28
+ def pvp_enabled? = data["IsPvpEnabled"]
29
+ def fall_damage_enabled? = data["IsFallDamageEnabled"]
30
+ def game_time_paused? = data["IsGameTimePaused"]
31
+ def game_time = data["GameTime"]
32
+
33
+ def spawning_npcs? = data["IsSpawningNPC"]
34
+ def npcs_frozen? = data["IsAllNPCFrozen"]
35
+
36
+ def daytime_duration = data["DaytimeDurationSeconds"] || 0
37
+ def nighttime_duration = data["NighttimeDurationSeconds"] || 0
38
+ def full_day_duration = (daytime_duration || 0) + (nighttime_duration || 0)
39
+
40
+ def death_settings
41
+ @death_settings ||= DeathSettings.new(data["Death"] || {})
42
+ end
43
+
44
+ def client_effects
45
+ @client_effects ||= ClientEffects.new(data["ClientEffects"] || {})
46
+ end
47
+
48
+ def saving_players? = data["IsSavingPlayers"]
49
+ def saving_chunks? = data["IsSavingChunks"]
50
+ def save_new_chunks? = data["SaveNewChunks"]
51
+ def unloading_chunks? = data["IsUnloadingChunks"]
52
+
53
+ def to_h = data
54
+
55
+ def name
56
+ return nil unless path
57
+
58
+ File.basename(File.dirname(path))
59
+ end
60
+
61
+ # Path is: /save_path/universe/worlds/world_name/config.json
62
+ def save_path
63
+ return nil unless path
64
+
65
+ File.expand_path("../../..", File.dirname(path))
66
+ end
67
+
68
+ def map
69
+ return nil unless path
70
+
71
+ Map.new(save_path, world_name: name)
72
+ end
73
+
74
+ class << self
75
+ def load(path)
76
+ raise NotFoundError, "World config not found: #{path}" unless File.exist?(path)
77
+
78
+ json = File.read(path)
79
+ data = JSON.parse(json)
80
+
81
+ new(data, path: path)
82
+ rescue JSON::ParserError => e
83
+ raise ParseError, "Failed to parse world config: #{e.message}"
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ class << self
6
+ def data_path
7
+ Config.data_path
8
+ end
9
+
10
+ def data_path=(path)
11
+ Config.data_path = path
12
+ end
13
+
14
+ def settings
15
+ Settings.load
16
+ end
17
+
18
+ def saves
19
+ Save.all
20
+ end
21
+
22
+ def save(name)
23
+ Save.find(name)
24
+ end
25
+
26
+ def launcher_log
27
+ LauncherLog.load
28
+ end
29
+
30
+ def prefabs
31
+ prefabs_path = Config.prefabs_path
32
+ return [] unless prefabs_path && File.directory?(prefabs_path)
33
+
34
+ Dir.glob(File.join(prefabs_path, "**", "*.lpf")).map do |path|
35
+ Prefab.load(path)
36
+ end
37
+ end
38
+
39
+ def prefab(name)
40
+ prefabs.find { |p| p.name == name || p.filename == name }
41
+ end
42
+
43
+ def prefab_categories
44
+ prefabs_path = Config.prefabs_path
45
+
46
+ return [] unless prefabs_path && File.directory?(prefabs_path)
47
+
48
+ Dir.children(prefabs_path).select do |entry|
49
+ File.directory?(File.join(prefabs_path, entry))
50
+ end.sort
51
+ end
52
+
53
+ def prefabs_in_category(category)
54
+ prefabs_path = Config.prefabs_path
55
+ return [] unless prefabs_path
56
+
57
+ category_path = File.join(prefabs_path, category)
58
+ return [] unless File.directory?(category_path)
59
+
60
+ Dir.glob(File.join(category_path, "**", "*.lpf")).map do |path|
61
+ Prefab.load(path)
62
+ end
63
+ end
64
+
65
+ def block_types
66
+ BlockType.all
67
+ end
68
+
69
+ def block_type(id)
70
+ BlockType.find(id) || BlockType.new(id)
71
+ end
72
+
73
+ def block_type_categories
74
+ BlockType.categories
75
+ end
76
+
77
+ def block_types_in_category(category)
78
+ BlockType.where(category: category)
79
+ end
80
+
81
+ alias blocks block_types
82
+ alias block block_type
83
+ alias block_categories block_type_categories
84
+ alias blocks_in_category block_types_in_category
85
+
86
+ def item_types
87
+ ItemType.all
88
+ end
89
+
90
+ def item_type(id)
91
+ ItemType.find(id) || ItemType.new(id)
92
+ end
93
+
94
+ def item_type_categories
95
+ ItemType.categories
96
+ end
97
+
98
+ def item_types_in_category(category)
99
+ ItemType.where(category: category)
100
+ end
101
+
102
+ alias items item_types
103
+ alias item item_type
104
+
105
+ def locales
106
+ Locale.all
107
+ end
108
+
109
+ def locale(code = Locale.default)
110
+ Locale.find(code) || Locale.new(code)
111
+ end
112
+
113
+ def players
114
+ saves.flat_map(&:players)
115
+ end
116
+
117
+ def player(uuid)
118
+ players.find { |p| p.uuid == uuid }
119
+ end
120
+
121
+ def player_skins
122
+ PlayerSkin.all
123
+ end
124
+
125
+ def player_skin(uuid)
126
+ PlayerSkin.find(uuid)
127
+ end
128
+
129
+ def installed?
130
+ Config.exists?
131
+ end
132
+
133
+ def running?
134
+ Process.running?
135
+ end
136
+
137
+ def processes
138
+ Process.list
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Server
5
+ class Process
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Server
5
+ end
6
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hytale
4
- VERSION = "0.0.1"
4
+ VERSION = "0.1.0"
5
5
  end
data/lib/hytale.rb CHANGED
@@ -1,8 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "hytale/version"
3
+ require "json"
4
+ require "time"
5
+ require "zeitwerk"
6
+
7
+ loader = Zeitwerk::Loader.for_gem
8
+ loader.inflector.inflect("npc_memory" => "NPCMemory")
9
+ loader.setup
4
10
 
5
11
  module Hytale
6
12
  class Error < StandardError; end
7
- # Your code goes here...
13
+ class NotFoundError < Error; end
14
+ class ParseError < Error; end
15
+
16
+ class << self
17
+ def client
18
+ Client
19
+ end
20
+
21
+ def settings
22
+ Client.settings
23
+ end
24
+
25
+ def saves
26
+ Client.saves
27
+ end
28
+
29
+ def players
30
+ Client.players
31
+ end
32
+
33
+ def launcher_log
34
+ Client.launcher_log
35
+ end
36
+
37
+ def server
38
+ Server
39
+ end
40
+ end
8
41
  end
42
+
43
+ loader.eager_load