chichilku3 14.0.4 → 15.0.2
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.
- checksums.yaml +4 -4
- data/bin/chichilku3 +1 -0
- data/bin/chichilku3-server +1 -0
- data/lib/client/chichilku3.rb +3 -1
- data/lib/client/client.rb +112 -59
- data/lib/client/client_cfg.rb +2 -1
- data/lib/client/gui.rb +219 -197
- data/lib/client/img/grass/single_64.png +0 -0
- data/lib/client/img/stick128/noarms/stick0.png +0 -0
- data/lib/client/img/stick128/noarms/stick1.png +0 -0
- data/lib/client/img/stick128/noarms/stick2.png +0 -0
- data/lib/client/img/stick128/noarms/stick3.png +0 -0
- data/lib/client/img/stick128/noarms/stick4.png +0 -0
- data/lib/client/img/stick128/noarms/stick5.png +0 -0
- data/lib/client/keys.rb +29 -0
- data/lib/client/particles.rb +54 -0
- data/lib/client/scoreboard.rb +29 -27
- data/lib/{client → external/gosu}/text.rb +29 -38
- data/lib/external/rubyzip/recursive.rb +58 -0
- data/lib/server/chichilku3_server.rb +169 -64
- data/lib/server/gamelogic.rb +107 -51
- data/lib/server/server_cfg.rb +2 -0
- data/lib/share/config.rb +22 -8
- data/lib/share/console.rb +22 -5
- data/lib/share/game_map.rb +279 -0
- data/lib/share/math.rb +14 -0
- data/lib/share/network.rb +47 -42
- data/lib/share/player.rb +168 -105
- data/lib/share/projectile.rb +97 -98
- data/lib/share/string.rb +24 -0
- data/server.json +3 -2
- metadata +46 -23
- data/lib/client/img/battle1024x576.png +0 -0
- data/lib/client/img/grass1024x512.png +0 -0
- data/lib/client/img/stick128/stick_noarms.png +0 -0
- data/lib/client/test.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13aef9c6c22c8ded3b9c9857f4e9c50a9e4ce83efb7067f1f4fe8ca82635a35d
|
4
|
+
data.tar.gz: 80ed6e70c0ab3d6daf7f44a540b209a6a418e7960d10259ce54530059b829713
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7112fcb7ac6b3dd34f4724a5079898583e47fb613450d4b0773db48831974881e5f8f1eb2b3bfdcb744b47ac5de9bbbd494a25158ba7c22b483850b933bbe101
|
7
|
+
data.tar.gz: fc5c6371d73ed88ef6dfa2d7a0e1d4881e9746fb644564705743c3724fb56129f692f89feb990f826a393d99ece0a3edf064f5b9939ccb3ca730a3af182a93a9
|
data/bin/chichilku3
CHANGED
data/bin/chichilku3-server
CHANGED
data/lib/client/chichilku3.rb
CHANGED
@@ -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,
|
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
|
-
|
10
|
-
|
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
|
-
|
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 =
|
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
|
-
|
54
|
-
start_recording
|
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
|
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 =
|
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.
|
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
|
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
|
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
|
-
|
154
|
+
case protocol
|
155
|
+
when 0 # error packet
|
144
156
|
code = data[0..2]
|
145
157
|
error_msg = data[3..-1]
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
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
|
-
|
158
|
-
@console.log
|
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
|
-
|
179
|
+
when 1 # update package
|
166
180
|
server_package_to_player_array(data)
|
167
|
-
|
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
|
-
|
187
|
+
when 3 # name packet
|
174
188
|
protocol_names(data)
|
175
|
-
|
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
|
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
|
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
|
-
|
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] ==
|
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
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
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,
|
347
|
-
new_player.projectile.r =
|
348
|
-
new_player.projectile.x =
|
349
|
-
new_player.projectile.y =
|
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
|
data/lib/client/client_cfg.rb
CHANGED
@@ -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']}'"
|