157 lines
3.9 KiB
Ruby
157 lines
3.9 KiB
Ruby
# Nathan Hinton 22 Dec 2025
|
|
# The main player file
|
|
|
|
require 'securerandom'
|
|
require 'yaml'
|
|
|
|
# A player object for the class Game
|
|
class Player
|
|
attr_reader :player_resources, :player_id, :player_planets, :player_ships, :faction, :researched_tech, :buildings
|
|
|
|
def initialize(player_id, faction)
|
|
@player_id = player_id
|
|
@player_planets = []
|
|
@player_ships = []
|
|
@home_planet = nil
|
|
|
|
# Validate faction:
|
|
if !(['good', 'evil'].include? faction)
|
|
raise PlayerError, 'Faction must be `good` or `evil`'
|
|
end
|
|
@faction = faction
|
|
end
|
|
|
|
# Create a new player. This is actually just setting it up. All the defaults
|
|
# are defined in the game_config.yaml file.
|
|
#
|
|
# @param credits [Integer] The number of starting credits
|
|
# @param metal [Integer] The amount of starting metal
|
|
# @param crystals [Integer] The number of starting crystals
|
|
# @param fuel [Integer] The amount of fuel to start with.
|
|
# @param faction [String] The faction that the player should start as. Should be `good` or `evil`
|
|
def create_new(credits, metal, crystals, fuel)
|
|
@player_resources = {
|
|
'credits' => credits,
|
|
'metal' => metal,
|
|
'crystals' => crystals,
|
|
'fuel' => fuel
|
|
}
|
|
end
|
|
|
|
# Connect a player
|
|
#
|
|
# @param client [TCPSocket] The socket used to communicate with the player
|
|
def connect(client)
|
|
@socket = client
|
|
end
|
|
|
|
# Returns if the player is connected or not
|
|
def connected?
|
|
if @socket.nil?
|
|
return false
|
|
elsif @socket.closed?
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
# Allows a player to claim a planet.
|
|
#
|
|
# @param planet
|
|
def claim_planet(planet)
|
|
if planet.claimable?
|
|
@player_planets.append(planet)
|
|
planet.claim(self)
|
|
end
|
|
end
|
|
|
|
# Makes a planet the player's home planet
|
|
#
|
|
# @param planet
|
|
def make_home_planet(planet)
|
|
if planet.owner == self
|
|
@home_planet = planet
|
|
else
|
|
return {'type' => 'error',
|
|
'payload' => 'Planet must be owned by the player'}
|
|
end
|
|
end
|
|
|
|
# Create an update to send out
|
|
def update(request_id)
|
|
planet_data = []
|
|
@player_planets.each do |planet|
|
|
planet_data.append(planet.info_update())
|
|
end
|
|
{
|
|
'type' => 'update',
|
|
'domain' => 'player',
|
|
'request_id' => request_id,
|
|
'payload' => {
|
|
'resources' => @player_resources,
|
|
'planets' => planet_data,
|
|
'ships' => @player_ships
|
|
}
|
|
}
|
|
end
|
|
|
|
# Used to send regular updates for the game data.
|
|
def send_update
|
|
# Send an update of all of the player data and stuff
|
|
return if !connected?
|
|
begin
|
|
@socket.puts(update(nil).to_json)
|
|
rescue
|
|
@socket.close
|
|
end
|
|
end
|
|
|
|
# Save a player to a file through marshaling it.
|
|
def save_to_file
|
|
File.open("game_data/#{@player_id}_player_.save", 'wb') do |fi|
|
|
# Load resources for the player:
|
|
fi.write(Marshal.dump(self))
|
|
end
|
|
return @player_id
|
|
end
|
|
|
|
# Load a player from a file. Requires the player id to load with as that is
|
|
# the file name.
|
|
def self.load_from_save(player_id)
|
|
File.open("game_data/#{player_id}_player_.save", 'rb') do |fi|
|
|
# Load resources for the player:
|
|
Marshal.load(fi.read)
|
|
end
|
|
end
|
|
|
|
# Custom funciton to dump marshal data for players. We do not want to try to
|
|
# dump the socket...
|
|
def marshal_dump
|
|
{
|
|
player_id: @player_id,
|
|
player_planets: @player_planets,
|
|
player_ships: @player_ships,
|
|
home_planet: @home_planet,
|
|
faction: @faction,
|
|
player_resources: @player_resources
|
|
}
|
|
end
|
|
|
|
# Custom function to load the marshaled data for the player.
|
|
#
|
|
# @param data [Hash] A hash containing the data.
|
|
def marshal_load(data)
|
|
@player_id = data[:player_id]
|
|
@player_planets = data[:player_planets]
|
|
@player_ships = data[:player_ships]
|
|
@home_planet = data[:home_planet]
|
|
@faction = data[:faction]
|
|
@player_resources = data[:player_resources]
|
|
end
|
|
end
|
|
|
|
|
|
# Errors for the player
|
|
class PlayerError < StandardError
|
|
end
|