mirror of
https://github.com/cyberarm/i-mic-rts.git
synced 2025-12-12 22:52:33 +00:00
Inital work on gamesaves/replays
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,5 +1,5 @@
|
||||
data/settings.json
|
||||
data/replays/*.replay
|
||||
data/saves/*.save
|
||||
data/replays/*.dat
|
||||
data/saves/*.dat
|
||||
doc/
|
||||
.yardoc/
|
||||
@@ -8,6 +8,7 @@ end
|
||||
|
||||
require "json"
|
||||
require "socket"
|
||||
require "digest/sha2"
|
||||
|
||||
require "nokogiri"
|
||||
|
||||
@@ -20,6 +21,7 @@ require_relative "lib/camera"
|
||||
require_relative "lib/setting"
|
||||
require_relative "lib/team_colors"
|
||||
require_relative "lib/constants"
|
||||
require_relative "lib/game_save"
|
||||
|
||||
require_relative "lib/states/boot"
|
||||
require_relative "lib/states/game"
|
||||
|
||||
@@ -2,7 +2,7 @@ class IMICRTS
|
||||
class Director
|
||||
attr_reader :current_tick, :map, :game, :players
|
||||
|
||||
def initialize(game:, map:, players: [], networking_mode:, tick_rate: 10, local_game: true, replay: false)
|
||||
def initialize(game:, map:, players:, networking_mode:, tick_rate: 15, local_game: true, replay: false, game_save: false, gamesave_file: nil)
|
||||
@game = game
|
||||
@map = map
|
||||
@players = players
|
||||
@@ -11,6 +11,10 @@ class IMICRTS
|
||||
@tick_rate = tick_rate
|
||||
@local_game = local_game
|
||||
@replay = replay
|
||||
@game_save = game_save
|
||||
@gamesave_file = gamesave_file ? gamesave_file : "#{IMICRTS::GAME_ROOT_PATH}/data/saves/savegame_#{Time.now.to_i}.dat"
|
||||
@game_save_host = GameSave.new(mode: :write, gamesave_file: @gamesave_file, players: players, map_file: @map.map_file, gamesave: true)
|
||||
@game_save_host.write_header
|
||||
|
||||
@last_tick_at = Gosu.milliseconds
|
||||
@tick_time = 1000.0 / @tick_rate
|
||||
@@ -25,8 +29,8 @@ class IMICRTS
|
||||
@replay
|
||||
end
|
||||
|
||||
def add_player(player)
|
||||
@players << player
|
||||
def game_save?
|
||||
@game_save
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -35,6 +39,7 @@ class IMICRTS
|
||||
|
||||
tick
|
||||
@connection.update
|
||||
@game_save_host&.feed_tick(@current_tick) if @replay
|
||||
end
|
||||
|
||||
@players.each { |player| player.update }
|
||||
@@ -58,6 +63,7 @@ class IMICRTS
|
||||
order_args = o.deserialize(order_data[1..order_data.length - 1], self)
|
||||
|
||||
execute_order(o.id, *order_args)
|
||||
@game_save_host&.write_order(order_data) unless @replay
|
||||
|
||||
player.orders.delete(order)
|
||||
|
||||
@@ -140,6 +146,7 @@ class IMICRTS
|
||||
def finalize
|
||||
@server&.stop
|
||||
@connection&.finalize
|
||||
@game_save_host&.finalize
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
50
lib/game_save.rb
Normal file
50
lib/game_save.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
class IMICRTS
|
||||
class GameSave
|
||||
def initialize(mode:, gamesave_file:, map_file: nil, players: nil, gamesave: false, player_id: nil)
|
||||
@mode = mode
|
||||
@gamesave_file = File.open(gamesave_file, "#{@mode == :write ? 'w' : 'r'}")
|
||||
@map_file = map_file
|
||||
@players = players
|
||||
@gamesave = gamesave
|
||||
@player_id = player_id
|
||||
|
||||
@version = IMICRTS::VERSION
|
||||
end
|
||||
|
||||
def parse
|
||||
#
|
||||
end
|
||||
|
||||
def feed_tick(tick_id)
|
||||
|
||||
end
|
||||
|
||||
def write_header
|
||||
player_data = @players.map do |player|
|
||||
{
|
||||
id: player.id,
|
||||
name: player.name,
|
||||
team: player.team,
|
||||
spawnpoint: player.spawnpoint,
|
||||
color: player.color&.gl,
|
||||
bot: player.bot
|
||||
}
|
||||
end
|
||||
|
||||
s = %{#{@version}
|
||||
#{@map_file}?#{Digest::SHA256.digest(File.read("#{IMICRTS::GAME_ROOT_PATH}/assets/#{@map_file}"))}
|
||||
#{@gamesave ? "GAMESAVE?#{@player_id}" : "REPLAY"}
|
||||
#{JSON.dump(player_data)}}
|
||||
|
||||
@gamesave_file.puts(s)
|
||||
end
|
||||
|
||||
def write_order(raw_order)
|
||||
@gamesave_file.puts(raw_order)
|
||||
end
|
||||
|
||||
def finalize
|
||||
@gamesave_file&.close
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,8 +1,9 @@
|
||||
class IMICRTS
|
||||
class Map
|
||||
attr_reader :tile_size, :tiles, :ores, :spawnpoints, :width, :height
|
||||
attr_reader :tile_size, :tiles, :ores, :spawnpoints, :width, :height, :map_file
|
||||
|
||||
def initialize(map_file:)
|
||||
@map_file = map_file
|
||||
@tiled_map = TiledMap.new(map_file)
|
||||
|
||||
@width = @tiled_map.width
|
||||
|
||||
@@ -11,24 +11,26 @@ class IMICRTS
|
||||
@options[:map] ||= Map.new(map_file: "maps/test_map.tmx")
|
||||
@options[:local_player_id] ||= 0
|
||||
|
||||
@director = Director.new(game: self, map: @options[:map], networking_mode: @options[:networking_mode])
|
||||
@options[:players] ||= [
|
||||
{ id: 0, team: 1, spawnpoint: @director.map.spawnpoints.last, color: :orange, bot: false },
|
||||
{ id: 1, team: 2, spawnpoint: @director.map.spawnpoints.first, color: :lightblue, bot: :brutal }
|
||||
{ id: 0, name: "0xdeadbeef", team: 1, spawnpoint: "B", color: :orange, bot: false },
|
||||
{ id: 1, name: "BrutalAI", team: 2, spawnpoint: "A", color: :lightblue, bot: :brutal }
|
||||
]
|
||||
|
||||
@options[:players].each do |pl|
|
||||
players = @options[:players].map do |pl|
|
||||
player = nil
|
||||
visiblity_map = VisibilityMap.new(width: @director.map.width, height: @director.map.height, tile_size: @director.map.tile_size)
|
||||
visiblity_map = VisibilityMap.new(width: @options[:map].width, height: @options[:map].height, tile_size: @options[:map].tile_size)
|
||||
unless pl[:bot]
|
||||
player = Player.new(id: pl[:id], spawnpoint: pl[:spawnpoint], team: pl[:team], color: TeamColors[pl[:color]], visiblity_map: visiblity_map)
|
||||
player = Player.new(id: pl[:id], name: pl[:name], spawnpoint: pl[:spawnpoint], team: pl[:team], color: TeamColors[pl[:color]], visiblity_map: visiblity_map)
|
||||
else
|
||||
player = AIPlayer.new(id: pl[:id], spawnpoint: pl[:spawnpoint], team: pl[:team], color: TeamColors[pl[:color]], bot: pl[:bot], visiblity_map: visiblity_map)
|
||||
player = AIPlayer.new(id: pl[:id], name: pl[:name], spawnpoint: pl[:spawnpoint], team: pl[:team], color: TeamColors[pl[:color]], bot: pl[:bot], visiblity_map: visiblity_map)
|
||||
end
|
||||
@player = player if player.id == @options[:local_player_id]
|
||||
@director.add_player(player)
|
||||
|
||||
player
|
||||
end
|
||||
|
||||
@director = Director.new(game: self, players: players, map: @options[:map], networking_mode: @options[:networking_mode])
|
||||
|
||||
@selected_entities = []
|
||||
@tool = set_tool(:entity_controller)
|
||||
@overlays = []
|
||||
@@ -61,9 +63,11 @@ class IMICRTS
|
||||
end
|
||||
|
||||
@director.players.each do |player|
|
||||
spawnpoint = @director.map.spawnpoints[player.spawnpoint.bytes.first - 65]
|
||||
|
||||
construction_yard = @director.spawn_entity(
|
||||
player_id: player.id, name: :construction_yard,
|
||||
position: CyberarmEngine::Vector.new(player.spawnpoint.x, player.spawnpoint.y, ZOrder::BUILDING)
|
||||
position: CyberarmEngine::Vector.new(spawnpoint.x, spawnpoint.y, ZOrder::BUILDING)
|
||||
)
|
||||
construction_yard.component(:structure).data.construction_progress = Entity.get(construction_yard.name).build_steps
|
||||
construction_yard.component(:structure).data.construction_complete = true
|
||||
@@ -77,7 +81,7 @@ class IMICRTS
|
||||
|
||||
@director.spawn_entity(
|
||||
player_id: player.id, name: :construction_worker,
|
||||
position: CyberarmEngine::Vector.new(player.spawnpoint.x - 64, player.spawnpoint.y + 64, ZOrder::GROUND_VEHICLE)
|
||||
position: CyberarmEngine::Vector.new(construction_yard.position.x - 64, construction_yard.position.y + 64, ZOrder::GROUND_VEHICLE)
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user