chichilku3 14.0.3 → 15.0.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/bin/chichilku3 +1 -0
  3. data/bin/chichilku3-server +1 -0
  4. data/lib/client/chichilku3.rb +3 -1
  5. data/lib/client/client.rb +112 -59
  6. data/lib/client/client_cfg.rb +2 -1
  7. data/lib/client/gui.rb +219 -197
  8. data/lib/client/img/stick128/arm64/arm0.png +0 -0
  9. data/lib/client/img/stick128/arm64/arm1.png +0 -0
  10. data/lib/client/img/stick128/arm64/arm2.png +0 -0
  11. data/lib/client/img/stick128/arm64/arm3.png +0 -0
  12. data/lib/client/img/stick128/noarms/stick0.png +0 -0
  13. data/lib/client/img/stick128/noarms/stick1.png +0 -0
  14. data/lib/client/img/stick128/noarms/stick2.png +0 -0
  15. data/lib/client/img/stick128/noarms/stick3.png +0 -0
  16. data/lib/client/img/stick128/noarms/stick4.png +0 -0
  17. data/lib/client/img/stick128/noarms/stick5.png +0 -0
  18. data/lib/client/keys.rb +29 -0
  19. data/lib/client/particles.rb +54 -0
  20. data/lib/client/scoreboard.rb +29 -27
  21. data/lib/{client → external/gosu}/text.rb +29 -38
  22. data/lib/external/rubyzip/recursive.rb +58 -0
  23. data/lib/server/chichilku3_server.rb +169 -64
  24. data/lib/server/gamelogic.rb +107 -51
  25. data/lib/server/server_cfg.rb +2 -0
  26. data/lib/share/config.rb +21 -7
  27. data/lib/share/console.rb +22 -5
  28. data/lib/share/game_map.rb +279 -0
  29. data/lib/share/math.rb +14 -0
  30. data/lib/share/network.rb +47 -42
  31. data/lib/share/player.rb +168 -105
  32. data/lib/share/projectile.rb +97 -98
  33. data/lib/share/string.rb +24 -0
  34. data/server.json +3 -2
  35. metadata +49 -23
  36. data/lib/client/img/battle1024x576.png +0 -0
  37. data/lib/client/img/grass1024x512.png +0 -0
  38. data/lib/client/img/stick128/stick_noarms.png +0 -0
  39. data/lib/client/test.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 539d73ce0c1c0eaed978079c9e5236339a0a198a8f6696a94a535332ebb36712
4
- data.tar.gz: db0db85ea83928af891accf3980119b4497fdb7803d459c06aa449801c671ce0
3
+ metadata.gz: 31045c6431444e15f1e7b4ae51bcbe4be2a3c9caeafa0807c99fa538ac098b5c
4
+ data.tar.gz: aa82eab01ecb488acd3c0526736eff6492eb9398bf7f2ee922225a8dc5b95690
5
5
  SHA512:
6
- metadata.gz: fb24df32cc1113d2b9610c38208c0c786939bb93c0d7549159ee90b4b834d6841f61be66da07973e231e89ba920f306da6eb9f39a0e57bac46907f49a8c46a1a
7
- data.tar.gz: 8f0ec76bf07d6be65c53c5a6d0935d068d51fc59c24aaa7acd201e48925f1c4ac272785c6faf3c33de7bf19d891747ae393c2041d963b156b3b82a5e3dc93759
6
+ metadata.gz: 7c2d2bba3f95541b65a3d07d1935c3d0911587df1f12e6bc13d797484a8045407fdac9ad3ee6682793d0c5860306f8a5b0bab9961e46a86d28235074e234a8f3
7
+ data.tar.gz: a902ddd4f25e47fa636c937e235534752e2e6b1b65fb63bc6f0f80ca0cd8aa32e480eb1f493289f10fb317e8bccbe4b02d166042620dfc60d05e20a29421f045
data/bin/chichilku3 CHANGED
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'client/chichilku3'
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'server/chichilku3_server'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'gosu'
2
4
  require_relative 'client'
3
5
  require_relative '../share/console'
@@ -9,7 +11,7 @@ require_relative 'client_cfg'
9
11
  class Game
10
12
  def initialize
11
13
  console = Console.new
12
- cfg = ClientCfg.new(console, "client.json")
14
+ cfg = ClientCfg.new(console, 'client.json')
13
15
  gui = Gui.new(cfg)
14
16
  gui.show
15
17
  end
data/lib/client/client.rb CHANGED
@@ -1,22 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'socket'
2
4
  require_relative '../share/network'
3
5
  require_relative '../share/player'
6
+ require_relative '../share/game_map'
4
7
 
5
8
  STATE_ERROR = -2
6
9
  STATE_MENU = -1
7
10
  STATE_OFFLINE = 0
8
11
  STATE_CONNECTING = 1
9
- STATE_INGAME = 2
10
- STATE_REC_PLAYBACK = 3
12
+ STATE_DOWNLOADING = 2
13
+ STATE_INGAME = 3
14
+ STATE_REC_PLAYBACK = 4
11
15
 
12
16
  # Networking part of the game clientside
13
17
  class Client
14
- attr_reader :id, :state, :server_version
15
- def initialize(console, cfg)
18
+ attr_reader :id, :state, :server_version, :game_map
19
+
20
+ def initialize(console, cfg, gui)
16
21
  @id = nil
17
22
  @tick = 0
18
23
  @state = STATE_MENU
19
24
  @cfg = cfg
25
+ @gui = gui
20
26
 
21
27
  @console = console
22
28
  @console.log "LOAD #{@s}"
@@ -25,39 +31,48 @@ class Client
25
31
 
26
32
  @recording_ticks = []
27
33
  @recording_ticks_len = 0
28
- @recording_file = "autorec.txt"
34
+ @recording_file = 'autorec.txt'
29
35
  @is_recording = false
30
36
 
31
37
  @server_version = nil
32
38
 
39
+ @game_map = nil
40
+
41
+ # @force_send
42
+ # used by client to send data regardless of what the gui
43
+ # wanted to send
44
+ @force_send = nil
45
+
33
46
  # state variables
34
47
  @req_playerlist = Time.now - 8
35
48
 
36
49
  # return values
37
50
  @players = []
38
- @flags = { skip: false, state: @state, gamestate: 'g',id: nil }
51
+ @flags = { skip: false, state: @state, gamestate: 'g', id: nil }
52
+ @extra = nil # currently only used for download progress array
39
53
  end
40
54
 
41
- def reset()
55
+ def reset
42
56
  @id = nil
43
57
  @tick = 0
44
58
  @state = STATE_MENU
45
59
  @players = []
46
- @flags = { skip: false, state: @state, gamestate: 'g',id: nil }
60
+ @flags = { skip: false, state: @state, gamestate: 'g', id: nil }
47
61
  end
48
62
 
49
63
  def connect(ip, port)
50
64
  reset
51
65
  @s = TCPSocket.open(ip, port)
52
66
  @s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) # nagle's algorithm-
53
- @state = STATE_CONNECTING
54
- start_recording() if @cfg.data['autorecord']
67
+ update_state(STATE_CONNECTING)
68
+ start_recording if @cfg.data['autorecord']
55
69
  end
56
70
 
57
- def disconnect()
71
+ def disconnect
58
72
  return if @state == STATE_MENU
73
+ return if @s.nil?
59
74
 
60
- @console.log "disconnecting from server."
75
+ @console.log 'disconnecting from server.'
61
76
  @s.close
62
77
  @s = nil
63
78
  reset
@@ -76,31 +91,27 @@ class Client
76
91
  @console.log "loaded recording containing #{@recording_ticks.size} ticks"
77
92
  end
78
93
 
79
- def start_recording()
80
- @recording_file = "autorec.txt"
94
+ def start_recording
95
+ @recording_file = 'autorec.txt'
81
96
  rec_file = "#{@cfg.chichilku3_dir}recordings/#{@recording_file}"
82
97
  @is_recording = true
83
- File.delete(rec_file) if File.exists? rec_file
98
+ File.delete(rec_file) if File.exist? rec_file
84
99
  end
85
100
 
86
101
  def recording_record_tick(data)
87
102
  return unless @is_recording
88
103
 
89
104
  recording_file = "#{@cfg.chichilku3_dir}recordings/#{@recording_file}"
90
- IO.write(recording_file, data + "\n", mode: 'a')
105
+ IO.write(recording_file, "#{data}\n", mode: 'a')
91
106
  end
92
107
 
93
- def recording_playback_tick()
108
+ def recording_playback_tick
94
109
  if @recording_ticks_len <= @tick
95
- @console.log "finished playing back recording"
110
+ @console.log 'finished playing back recording'
96
111
  update_state(STATE_MENU)
97
112
  return [[], @flags, nil]
98
113
  end
99
114
  data = @recording_ticks[@tick]
100
- if data.length != SERVER_PACKAGE_LEN
101
- @console.err "failed to parse recording data=#{data.length} server=#{SERVER_PACKAGE_LEN}"
102
- return nil
103
- end
104
115
 
105
116
  @tick += 1
106
117
  @flags[:skip] = false
@@ -128,7 +139,7 @@ class Client
128
139
 
129
140
  # save protocol and cut it off
130
141
  msg = handle_protocol(data[0].to_i, data[1], data[2..-1])
131
- [@players, @flags, msg]
142
+ [@players, @flags, msg, @extra]
132
143
  end
133
144
 
134
145
  private
@@ -140,43 +151,75 @@ class Client
140
151
 
141
152
  def handle_protocol(protocol, p_status, data)
142
153
  @console.dbg "HANDLE PROTOCOL=#{protocol} status=#{p_status}"
143
- if protocol == 0 # error packet
154
+ case protocol
155
+ when 0 # error packet
144
156
  code = data[0..2]
145
157
  error_msg = data[3..-1]
146
- if code == NET_ERR_FULL
147
- @console.log "server is full."
148
- elsif code == NET_ERR_DISCONNECT
149
- @console.log "disconnected by server."
150
- elsif code == NET_ERR_KICK
151
- @console.log "kicked by server."
152
- elsif code == NET_ERR_BAN
153
- @console.log "banned by server."
154
- elsif code == NET_ERR_SERVER_OUTDATED
155
- @console.log "failed to connect to server: server is outdated."
158
+ case code
159
+ when NET_ERR_FULL
160
+ @console.log 'server is full.'
161
+ when NET_ERR_DISCONNECT
162
+ @console.log 'disconnected by server.'
163
+ when NET_ERR_KICK
164
+ @console.log 'kicked by server.'
165
+ when NET_ERR_BAN
166
+ @console.log 'banned by server.'
167
+ when NET_ERR_SERVER_OUTDATED
168
+ @console.log 'failed to connect to server: server is outdated.'
156
169
  @console.log error_msg
157
- elsif code == NET_ERR_CLIENT_OUTDATED
158
- @console.log "failed to connect to server: your client is outdated."
170
+ when NET_ERR_CLIENT_OUTDATED
171
+ @console.log 'failed to connect to server: your client is outdated.'
159
172
  else
160
173
  @console.log "ERROR unkown error code code=#{code} data=#{data}"
161
174
  return
162
175
  end
176
+ disconnect
163
177
  @state = STATE_ERROR
164
178
  return [0, code, error_msg]
165
- elsif protocol == 1 # update package
179
+ when 1 # update package
166
180
  server_package_to_player_array(data)
167
- elsif protocol == 2 # id packet
181
+ when 2 # id packet
168
182
  if @id.nil?
169
183
  id_packet(data)
170
184
  else
171
185
  @console.log "WARNING got unexpected id packet=#{data}"
172
186
  end
173
- elsif protocol == 3 # name packet
187
+ when 3 # name packet
174
188
  protocol_names(data)
175
- elsif protocol == 4 # command respond
189
+ when 4 # command respond
176
190
  @console.log "server respond: #{data}"
177
191
  return [1, data]
192
+ when 5 # map info
193
+ checksum = data[0..39]
194
+ @game_map = GameMap.new(@console, @cfg, nil, method(:finished_download_callback), checksum)
195
+ when 6 # map download init
196
+ size = net_unpack_bigint(data[0..5])
197
+ mapname = data[6..-1].strip
198
+ @game_map.set_name(mapname)
199
+ @game_map.set_size(size)
200
+ accept = '0'
201
+ if @game_map.found?
202
+ @console.log "loading map name='#{mapname}'"
203
+ finished_download_callback(@game_map.dl_path)
204
+ else
205
+ @console.log "downloading map name='#{mapname}' size=#{size} ..."
206
+ update_state(STATE_DOWNLOADING)
207
+ @game_map.prepare_download
208
+ accept = '1'
209
+ end
210
+ @force_send = "5l#{@id.to_s(16)}#{accept}b641000"
211
+ when 7 # map download chunk
212
+ if @game_map.nil?
213
+ @console.wrn 'got unexpected map chunk from server (no map)'
214
+ @force_send = "5l#{@id.to_s(16)}0b641000"
215
+ elsif @state != STATE_DOWNLOADING
216
+ @console.wrn 'got unexpected map chunk from server (wrong client state)'
217
+ @force_send = "5l#{@id.to_s(16)}0b641000"
218
+ else
219
+ @extra = [@game_map.download(data), @game_map.size]
220
+ end
178
221
  else
179
- @console.log "ERROR unkown protocol=#{protocol} data=#{data}"
222
+ @console.log "ERROR unkown protocol=#{protocol} data='#{data}'"
180
223
  end
181
224
  nil
182
225
  end
@@ -198,11 +241,16 @@ class Client
198
241
  return
199
242
  end
200
243
 
244
+ unless @force_send.nil?
245
+ net_write(@force_send)
246
+ @force_send = nil
247
+ end
248
+
201
249
  data = "#{protocol}l#{@id.to_s(16)}#{data.join('')}"
202
250
  net_write(data)
203
251
  end
204
252
 
205
- def set_id(id)
253
+ def update_id(id)
206
254
  if id > MAX_CLIENTS || id < 1
207
255
  @console.log "Errornous id=#{id}"
208
256
  return false
@@ -217,8 +265,7 @@ class Client
217
265
  @console.log 'Trying to read id...'
218
266
  @playercount = net_unpack_int(data[0..1])
219
267
  id = data[2].to_i(16)
220
- set_id(id)
221
- update_state(STATE_INGAME) unless @state == STATE_REC_PLAYBACK
268
+ update_id(id)
222
269
  end
223
270
 
224
271
  def id_packet(data)
@@ -238,11 +285,11 @@ class Client
238
285
  server_data = save_read(@s, 3)
239
286
  return nil if server_data == ''
240
287
 
241
- if server_data[0] == "1"
288
+ if server_data[0] == '1'
242
289
  len = net_unpack_int(server_data[2]) * PLAYER_PACKAGE_LEN
243
- server_data += save_read(@s, len+1)
290
+ server_data += save_read(@s, len + 1)
244
291
  else
245
- server_data += save_read(@s, SERVER_PACKAGE_LEN-3)
292
+ server_data += save_read(@s, SERVER_PACKAGE_LEN - 3)
246
293
  end
247
294
  return nil if server_data == ''
248
295
 
@@ -259,6 +306,12 @@ class Client
259
306
  @console.dbg "sent: #{data}"
260
307
  end
261
308
 
309
+ def finished_download_callback(map_dir)
310
+ update_state(STATE_INGAME) unless @state == STATE_REC_PLAYBACK
311
+ @gui.load_background_image(map_dir)
312
+ @game_map.load_data(map_dir)
313
+ end
314
+
262
315
  # TODO: add protocol class for this
263
316
  # TODO: protocol_names should create the player objects
264
317
  # AND: server_package_to_player_array should update the objs
@@ -278,7 +331,7 @@ class Client
278
331
  players = []
279
332
  used_slots.times do |index|
280
333
  size = NAME_LEN + 2 # id|score|name
281
- players[index] = data[index * size..index * size + size-1]
334
+ players[index] = data[index * size..index * size + size - 1]
282
335
  end
283
336
  players
284
337
  end
@@ -288,7 +341,7 @@ class Client
288
341
  player_strs.each do |player_str|
289
342
  id = player_str[0].to_i(16)
290
343
  score = net_unpack_int(player_str[1])
291
- name = player_str[2..-1]
344
+ name = player_str[2..-1].strip
292
345
  players << Player.new(id, 0, 0, score, name) unless id.zero?
293
346
  end
294
347
  # debug
@@ -315,7 +368,7 @@ class Client
315
368
  def server_package_to_player_strs(used_slots, data)
316
369
  players = []
317
370
  used_slots.times do |index|
318
- players[index] = data[index * PLAYER_PACKAGE_LEN..index * PLAYER_PACKAGE_LEN + PLAYER_PACKAGE_LEN-1]
371
+ players[index] = data[index * PLAYER_PACKAGE_LEN..index * PLAYER_PACKAGE_LEN + PLAYER_PACKAGE_LEN - 1]
319
372
  end
320
373
  players
321
374
  end
@@ -326,11 +379,11 @@ class Client
326
379
  id = player_str[0].to_i(16)
327
380
  score = net_unpack_int(player_str[1])
328
381
  net_state = player_str[2]
329
- projR = player_str[3]
330
- projX = net_unpack_bigint(player_str[4..5])
331
- projY = net_unpack_bigint(player_str[6..7])
332
- aimX = net_unpack_bigint(player_str[8..9])
333
- aimY = net_unpack_bigint(player_str[10..11])
382
+ proj_r = player_str[3]
383
+ proj_x = net_unpack_bigint(player_str[4..5])
384
+ proj_y = net_unpack_bigint(player_str[6..7])
385
+ aim_x = net_unpack_bigint(player_str[8..9])
386
+ aim_y = net_unpack_bigint(player_str[10..11])
334
387
  x = net_unpack_bigint(player_str[12..13])
335
388
  y = net_unpack_bigint(player_str[14..15])
336
389
  # puts "'#{player_str}' id: #{id} x: #{x} '#{player_str[12..13]}' y: #{y} '#{player_str[14..15]}'"
@@ -343,10 +396,10 @@ class Client
343
396
  next if p_index.nil?
344
397
 
345
398
  @console.dbg "got player: #{@players[p_index]}"
346
- new_player = Player.update_player(@players, id, x, y, score, aimX, aimY)
347
- new_player.projectile.r = projR
348
- new_player.projectile.x = projX
349
- new_player.projectile.y = projY
399
+ new_player = Player.update_player(@players, id, x, y, score, aim_x, aim_y)
400
+ new_player.projectile.r = proj_r
401
+ new_player.projectile.x = proj_x
402
+ new_player.projectile.y = proj_y
350
403
  new_player.net_to_state(net_state)
351
404
  @players[Player.get_player_index_by_id(@players, id)] = new_player
352
405
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require_relative '../share/network'
3
5
  require_relative '../share/config'
@@ -5,7 +7,6 @@ require_relative '../share/config'
5
7
  # The client side repository using JSON
6
8
  class ClientCfg < Config
7
9
  def sanitize_data(data)
8
- data = JSON.parse(File.read(@file))
9
10
  if data['username'].length > NAME_LEN
10
11
  data['username'] = data['username'][0..NAME_LEN - 1]
11
12
  @console.log "username to long chopped to '#{data['username']}'"