Files
space_game_server/lib/game/building.rb
T

135 lines
4.4 KiB
Ruby

# Nathan Hinton Jan 2026
# Game file for the buildings
require 'securerandom'
# Load the ships into a constant:
require 'yaml'
BUILDING_DATA = File.open('lib/game/data/buildings.yaml', 'r') do |fi|
YAML.safe_load(fi.read())
end
class Building
attr_reader :name
# Create a building. Requires a player and a planet to construct on.
#
# @param player [Player] The player who owns the building.
# @param planet [Planet] The planet the building should be built on.
# @param name [String] The name of the building to be built.
def initialize(player, planet, name)
@player = player
@planet = planet
@name = name
@building_exist_time = 0
@building_last_production_time = 0
# Return error if the building does not exist
@building = BUILDING_DATA[name]
if @building.nil?
raise BuildingError, "Invalid building name `#{name}`"
end
# Check the player owns the planet
if planet.owner != player
raise BuildingError, 'Player does not own planet!'
end
# Check the player has the resources
resources = ['metal', 'crystals', 'fuel', 'credits']
resources.each do |resource|
if @player.player_resources[resource] < @building['build_cost'][resource]
raise BuildingError, "Player does not have enough #{resource}!"
end
end
resources.each do |resource|
@player.player_resources[resource] -= @building['build_cost'][resource]
end
# Check that the player owns the needed buildings to construct:
player_buildings = @player.all_buildings.map{|building| building.name}
@building['required_buildings'].each do |required_building|
unless player_buildings.include? required_building
raise BuildingError, "Requires `#{required_building}` first"
end
end
# Check that the player owns the needed tech to construct:
player_tech = @player.all_tech.map{|tech| tech.name}
@building['required_tech'].each do |required_tech|
unless player_tech.include? required_tech
raise BuildingError, "Requires the tech of `#{required_tech}` first"
end
end
end
# This is in charge of doing things like adding to the turn build power and
# providing resources from buildings.
def update(delta_time)
@building_exist_time += delta_time
# Incriment internal time count:
# Do not produce resources if the building is not finished
if @building_exist_time < @building['build_cost']['time']
return # Exit
end
# Do not produce resources if there are not enough resources for upkeep
resources = ['metal', 'crystals', 'fuel', 'credits']
resources.each do |resource|
if @player.player_resources[resource * delta_time] < @building['upkeep'][resource * delta_time]
raise BuildingWarning, "Player does not have enough #{resource} to produce from #{@name}!"
end
end
resources.each do |resource|
@player.player_resources[resource * delta_time] -= @building['upkeep'][resource * delta_time]
end
@building_last_production_time += delta_time
# If the building is a resource production building we need to add the resources:
if @building['classification'] == 'mining'
if @building_last_production_time >= 1
@building_last_production_time -= 1
resources.each do |resource|
# This resource production should jump
@player.player_resources[resource] += @building['produces'][resource]
end
end
elsif @building['classification'] == 'production'
@player.ship_build_power += @building['produces']['ship_build_power']
@player.research_tech_build_power += @building['produces']['research_tech_build_power']
@player.military_tech_build_power += @building['produces']['military_tech_build_power']
else
raise BuildingError, 'Unknown classification for building type. Trying to add resources etc...'
end
end
# Save a player to a file
def save_to_file
File.open("game_data/#{self.planet_id}.save", 'wb') do |fi|
# Load resources for the player:
fi.write(Marshal.dump(self))
end
return self.planet_id
end
# Load a player from a file
def self.load_from_save(fname)
File.open("game_data/#{fname}_ship_.save", 'rb') do |fi|
# Load resources for the player:
Marshal.load(fi.read)
end
end
end
# Error class for the buildings
class BuildingError < StandardError
end
# Warning class for the buildings
class BuildingWarning < StandardError
end