Class: GameMap

Inherits:
Object
  • Object
show all
Defined in:
lib/share/game_map.rb

Overview

GameMap class handles the game_map file format

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(console, cfg, mapname, callback = nil, checksum = nil) ⇒ GameMap

Returns a new instance of GameMap.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/share/game_map.rb', line 22

def initialize(console, cfg, mapname, callback = nil, checksum = nil)
  @console = console
  @cfg = cfg
  @mapname = mapname
  @b64_size = -1
  @b64_data = ''
  @sha1sum = checksum
  @gametiles = []
  # grass_rows
  #   array of hashes containing connected grass tiles
  #   a row of grass from x 0 to x 10 at the height 2 would look like this
  #   {x1: 0, x2: 10, y: 2}
  @grass_rows = []
  @ready = false
   = nil

  # client
  @callback = callback
  @progress = 0
  @tmpfile = nil
end

Instance Attribute Details

#gametilesObject (readonly)

Returns the value of attribute gametiles.



20
21
22
# File 'lib/share/game_map.rb', line 20

def gametiles
  @gametiles
end

#grass_rowsObject (readonly)

Returns the value of attribute grass_rows.



20
21
22
# File 'lib/share/game_map.rb', line 20

def grass_rows
  @grass_rows
end

#metadataObject (readonly)

Returns the value of attribute metadata.



20
21
22
# File 'lib/share/game_map.rb', line 20

def 
  
end

#readyObject (readonly)

Returns the value of attribute ready.



20
21
22
# File 'lib/share/game_map.rb', line 20

def ready
  @ready
end

Instance Method Details

#checksumObject



44
45
46
# File 'lib/share/game_map.rb', line 44

def checksum
  @sha1sum
end

#collision?(x, y) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
# File 'lib/share/game_map.rb', line 146

def collision?(x, y)
  { x: x, y: y } if @gametiles[y][x] == 'O'
end

#death?(x, y) ⇒ Boolean

Returns:

  • (Boolean)


142
143
144
# File 'lib/share/game_map.rb', line 142

def death?(x, y)
  { x: x, y: y } if @gametiles[y][x] == 'X'
end

#dl_pathObject

CLIENT



224
225
226
# File 'lib/share/game_map.rb', line 224

def dl_path
  "#{@cfg.chichilku3_dir}downloadedmaps/#{@mapname}_#{checksum}"
end

#download(data) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
# File 'lib/share/game_map.rb', line 233

def download(data)
  data.strip!
  @progress += data.size
  @console.dbg "downloading #{@progress} / #{@b64_size} ..."
  IO.write(@tmpfile, data, mode: 'a')
  if @progress >= @b64_size
    @console.log 'finished download'
    @callback.call(load)
  end
  @progress
end

#encodeObject



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/share/game_map.rb', line 196

def encode
  rawfile = "#{@cfg.chichilku3_dir}maps/#{@mapname}.zip"
  @console.log "encoding map archive '#{@mapname}' ..."
  File.open(rawfile, 'rb') do |map_png|
    raw_content = map_png.read
    @sha1sum = Digest::SHA1.hexdigest raw_content
    encodefile = "#{@cfg.chichilku3_dir}maps_b64/#{@mapname}_#{checksum}.zip"
    File.open(encodefile, 'wb') do |map_encoded|
      @b64_data = Base64.encode64(raw_content).delete! "\n"
      @b64_size = @b64_data.size
      map_encoded.write(@b64_data)
    end
  end
  @console.log "finished encoding size=#{@b64_size} checksum=#{checksum}"
end

#found?Boolean

Returns:

  • (Boolean)


245
246
247
# File 'lib/share/game_map.rb', line 245

def found?
  File.directory? dl_path
end

#get_data(offset, size) ⇒ Object



212
213
214
215
216
217
218
219
220
# File 'lib/share/game_map.rb', line 212

def get_data(offset, size)
  return nil if @mapname == '' || @mapname.nil?

  if offset + size > @b64_size
    @b64_data[offset..-1].ljust(size, ' ')
  else
    @b64_data[offset...offset + size]
  end
end

#grass?(x, y) ⇒ Boolean

Returns:

  • (Boolean)


150
151
152
# File 'lib/share/game_map.rb', line 150

def grass?(x, y)
  { x: x, y: y } if @gametiles[y][x] == 'i'
end

#loadObject



267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/share/game_map.rb', line 267

def load
  outfile = "#{dl_path}.zip"
  @console.log 'converting downloaded map ...'
  File.open(@tmpfile, 'rb') do |map_encoded|
    File.open(outfile, 'wb') do |map_png|
      map_png.write(
        Base64.decode64(map_encoded.read)
      )
    end
  end
  unzip
end

#load_data(map_dir) ⇒ Object



136
137
138
139
140
# File 'lib/share/game_map.rb', line 136

def load_data(map_dir)
  load_gametiles(map_dir)
  (map_dir)
  @ready = true
end

#load_gametiles(map_dir) ⇒ Object

rubocop:enable Naming/AccessorMethodName



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/share/game_map.rb', line 71

def load_gametiles(map_dir)
  gamefile = "#{map_dir}/gametiles.txt"
  unless File.exist? gamefile
    @console.err "could not load gametiles '#{gamefile}'"
    exit 1
  end

  is_skip = true
  @gametiles = []
  @grass_rows = []
  File.readlines(gamefile).each_with_index do |data, i|
    gamerow = data[0..-2] # cut off newline
    is_skip = !is_skip if gamerow =~ /\+-+\+/
    gamerow = gamerow.match(/\|(.*)\|/)
    next if gamerow.nil?

    gamerow = gamerow[1]
    next if is_skip

    if gamerow.length != MAP_WIDTH
      @console.err "invalid gametiles row=#{i} size=#{gamerow.length}/#{MAP_WIDTH}"
      exit 1
    end
    @gametiles << gamerow
  end
  if @gametiles.length != MAP_HEIGHT
    @console.err "invalid gametiles rows=#{@gametiles.length}/#{MAP_HEIGHT}"
    exit 1
  end
  y = 0
  grass = {}
  @gametiles.each do |gamerow|
    x = 0
    gamerow.chars.each do |tile|
      if tile == 'i'
        grass[:x2] = x * TILE_SIZE + TILE_SIZE
        grass[:y] = y * TILE_SIZE + TILE_SIZE / 2 + 2
        grass[:x1] = x * TILE_SIZE if grass[:x1].nil?
      else
        @grass_rows.push(grass) unless grass == {}
        grass = {}
      end
      x += 1
    end
    y += 1
  end
  nil
end

#load_metadata(map_dir) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/share/game_map.rb', line 120

def (map_dir)
  metafile = "#{map_dir}/metadata.json"
  unless File.exist? metafile
    @console.err "could not load gametiles '#{metafile}'"
    exit 1
  end

   = JSON.parse(File.read(metafile))
  if ['chichilku3-map-version'] != MAP_VERSION
    @console.err "Failed to load map '#{@metadata['name']}':"
    @console.err "  Expected map version '#{MAP_VERSION}' but got '#{@metadata['chichilku3-map-version']}'"
    exit 1
  end
  @console.log "loaded map '#{@metadata['name']}' (#{@metadata['version']}) by #{@metadata['authors'].join(',')}"
end

#nameObject



48
49
50
# File 'lib/share/game_map.rb', line 48

def name
  @mapname
end

#prepare_downloadObject



228
229
230
231
# File 'lib/share/game_map.rb', line 228

def prepare_download
  @tmpfile = "#{@cfg.chichilku3_dir}tmp/#{@mapname}"
  File.delete @tmpfile if File.exist? @tmpfile
end

#prepare_uploadObject

SERVER



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/share/game_map.rb', line 156

def prepare_upload
  return if @mapname == '' || @mapname.nil?

  map_dir = "#{@cfg.chichilku3_dir}maps/#{@mapname}"
  unless File.directory? map_dir
    @console.err "failed to load map '#{@mapname}' (directory not found)"
    exit 1
  end
  unless File.exist? "#{map_dir}/background.png"
    @console.err "failed to load map '#{@mapname}' (no background.png)"
    exit 1
  end
  unless File.exist? "#{map_dir}/gametiles.txt"
    @console.err "failed to load map '#{@mapname}' (no gametiles.txt)"
    exit 1
  end
  load_data(map_dir)
  zip
  encode
end

#set_name(name) ⇒ Object

TODO: fix this rubocop rubocop:disable Naming/AccessorMethodName



54
55
56
57
58
# File 'lib/share/game_map.rb', line 54

def set_name(name)
  raise unless @mapname.nil?

  @mapname = name
end

#set_size(size) ⇒ Object



64
65
66
67
68
# File 'lib/share/game_map.rb', line 64

def set_size(size)
  raise unless @b64_size == -1

  @b64_size = size
end

#sizeObject



60
61
62
# File 'lib/share/game_map.rb', line 60

def size
  @b64_size
end

#unzipObject



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/share/game_map.rb', line 249

def unzip
  map_archive = "#{dl_path}.zip"
  map_dir = dl_path
  FileUtils.mkdir_p map_dir
  Dir.chdir map_dir do
    Zip::File.open(map_archive) do |zip_file|
      zip_file.each do |entry|
        @console.log "extracting '#{entry.name}' ...'"
        raise 'File too large when extracted' if entry.size > MAX_UNZIP_SIZE

        entry.extract
      end
    end
  end
  File.delete map_archive if File.exist? map_archive
  map_dir
end

#zipObject



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/share/game_map.rb', line 177

def zip
  map_dir = "#{@cfg.chichilku3_dir}maps/#{@mapname}"
  map_zip = "#{@cfg.chichilku3_dir}maps/#{@mapname}.zip"
  File.delete map_zip if File.exist? map_zip

  @console.log "archiving map '#{map_zip}' ..."
  Zip::File.open(map_zip, Zip::File::CREATE) do |zipfile|
    MAP_FILES.each do |filename|
      filepath = File.join(map_dir, filename)
      unless File.exist? filepath
        @console.err "failed to zip map '#{@mapname}' missing file:"
        @console.err filepath
        exit 1
      end
      zipfile.add(filename, filepath)
    end
  end
end