hytale 0.0.1 → 0.1.1

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +21 -0
  3. data/README.md +1430 -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 +57 -0
  12. data/lib/hytale/client/launcher_log.rb +99 -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 +695 -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 +435 -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 +54 -0
  25. data/lib/hytale/client/player/item.rb +102 -0
  26. data/lib/hytale/client/player/item_storage.rb +40 -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 +101 -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 +74 -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/zone/region.rb +52 -0
  50. data/lib/hytale/client/zone.rb +68 -0
  51. data/lib/hytale/client.rb +142 -0
  52. data/lib/hytale/server/process.rb +11 -0
  53. data/lib/hytale/server.rb +6 -0
  54. data/lib/hytale/version.rb +1 -1
  55. data/lib/hytale.rb +37 -2
  56. metadata +119 -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,74 @@
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
+ def fullscreen? = data["Fullscreen"]
14
+ def maximized? = data["Maximized"]
15
+ def window_width = data["WindowWidth"]
16
+ def window_height = data["WindowHeight"]
17
+ def window_size = [window_width, window_height]
18
+ def vsync? = data["VSync"]
19
+ def fps_limit = data["FpsLimit"]
20
+ def unlimited_fps? = data["UnlimitedFps"]
21
+ def field_of_view = data["FieldOfView"]
22
+
23
+ def rendering
24
+ @rendering ||= RenderingSettings.new(data["RenderingSettings"] || {})
25
+ end
26
+
27
+ def input_bindings
28
+ @input_bindings ||= InputBindings.new(data["InputBindings"] || {})
29
+ end
30
+
31
+ def mouse_settings
32
+ @mouse_settings ||= MouseSettings.new(data["MouseSettings"] || {})
33
+ end
34
+
35
+ def audio
36
+ @audio ||= AudioSettings.new(data["AudioSettings"] || {})
37
+ end
38
+
39
+ def gameplay
40
+ @gameplay ||= GameplaySettings.new(data["GameplaySettings"] || {})
41
+ end
42
+
43
+ def builder_tools
44
+ @builder_tools ||= BuilderToolsSettings.new(data["BuilderToolsSettings"] || {})
45
+ end
46
+
47
+ def hide_hud? = data["HideHud"]
48
+ def hide_hotbar? = data["HideHotbar"]
49
+ def hide_compass? = data["HideCompass"]
50
+ def hide_chat? = data["HideChat"]
51
+ def diagnostic_mode? = data["DiagnosticMode"]
52
+ def display_combat_text? = data["DisplayCombatText"]
53
+ def sprint_fov_effect? = data["SprintFovEffect"]
54
+ def view_bobbing_effect? = data["ViewBobbingEffect"]
55
+ def camera_shake_effect? = data["CameraShakeEffect"]
56
+
57
+ def to_h
58
+ data
59
+ end
60
+
61
+ class << self
62
+ def load(path: Config.settings_path)
63
+ raise NotFoundError, "Settings file not found: #{path}" unless File.exist?(path)
64
+
65
+ json = File.read(path)
66
+ data = JSON.parse(json)
67
+ new(data, path: path)
68
+ rescue JSON::ParserError => e
69
+ raise ParseError, "Failed to parse settings: #{e.message}"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ 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,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ module Zone
6
+ class Region
7
+ class << self
8
+ def all
9
+ Locale.regions.keys.map { |id| new(id) }
10
+ end
11
+
12
+ def find(id)
13
+ new(id) if Locale.region_name(id)
14
+ end
15
+ end
16
+
17
+ attr_reader :id
18
+
19
+ def initialize(id)
20
+ @id = id
21
+ end
22
+
23
+ def name
24
+ Locale.region_name(id) || id
25
+ end
26
+
27
+ def zone
28
+ zone_id = REGION_PREFIX_TO_ZONE.find { |prefix, _| id.start_with?(prefix) }&.last
29
+
30
+ Zone.new(zone_id) if zone_id
31
+ end
32
+
33
+ def to_s = name
34
+ def inspect = "#<Zone::Region id=#{id.inspect} name=#{name.inspect}>"
35
+
36
+ def ==(other)
37
+ case other
38
+ when Region then id == other.id
39
+ when String then id == other
40
+ else false
41
+ end
42
+ end
43
+
44
+ alias eql? ==
45
+
46
+ def hash
47
+ id.hash
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Client
5
+ module Zone
6
+ ZONE_TO_REGION_PREFIX = {
7
+ "Emerald_Wilds" => "Zone1",
8
+ "Howling_Sands" => "Zone2",
9
+ "Whisperfrost_Frontiers" => "Zone3",
10
+ "Devastated_Lands" => "Zone4",
11
+ "Oceans" => "Oceans",
12
+ }.freeze
13
+
14
+ REGION_PREFIX_TO_ZONE = ZONE_TO_REGION_PREFIX.invert.freeze
15
+
16
+ class << self
17
+ def all
18
+ Locale.zones.keys.map { |id| new(id) }
19
+ end
20
+
21
+ def find(id)
22
+ new(id) if Locale.zone_name(id)
23
+ end
24
+
25
+ def new(id)
26
+ Zone::Base.new(id)
27
+ end
28
+ end
29
+
30
+ class Base
31
+ attr_reader :id
32
+
33
+ def initialize(id)
34
+ @id = id
35
+ end
36
+
37
+ def name
38
+ Locale.zone_name(id) || id
39
+ end
40
+
41
+ def regions
42
+ prefix = ZONE_TO_REGION_PREFIX[id]
43
+
44
+ return [] unless prefix
45
+
46
+ Region.all.select { |region| region.id.start_with?(prefix) }
47
+ end
48
+
49
+ def to_s = name
50
+ def inspect = "#<Zone id=#{id.inspect} name=#{name.inspect}>"
51
+
52
+ def ==(other)
53
+ case other
54
+ when Base then id == other.id
55
+ when String then id == other
56
+ else false
57
+ end
58
+ end
59
+
60
+ alias eql? ==
61
+
62
+ def hash
63
+ id.hash
64
+ end
65
+ end
66
+ end
67
+ end
68
+ 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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hytale
4
+ module Server
5
+ class Process
6
+ def self.running?
7
+ false
8
+ end
9
+ end
10
+ end
11
+ 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.1"
5
5
  end