termfront 0.1.1 → 0.1.3
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/.ruby-version +1 -0
- data/CHANGELOG.md +18 -0
- data/README.md +9 -1
- data/lib/termfront/network/client.rb +85 -0
- data/lib/termfront/network/connection.rb +47 -3
- data/lib/termfront/network/server.rb +10 -5
- data/lib/termfront/version.rb +1 -1
- metadata +93 -93
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64c01550bc002aa40824296474323c7dc6126447fe52bd8acb8cf150514a68af
|
|
4
|
+
data.tar.gz: 07c871ac0a859394d94d98189700195a8a98469c0f319d8748482ff79f617883
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 665f32c4d60b34330ba53c5beafed57826c5b1402a9855c613cd40941dbb4ea8bd29dd93eeb564b90513809d7f26e7f649624d1fe749054ead899884865f74c3
|
|
7
|
+
data.tar.gz: 5d5f99b125210dbf8980cea284f112279178d228499f1caad9880deb99869cced727bfd180d5b1b8db645c10aa6627c7ba79e218b6093fd8e74b37f2bf5bf102
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.5
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,24 @@ The format is based on Keep a Changelog, and this project follows Semantic Versi
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.1.3] - 2026-05-24
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed TLS server certificate loading to include intermediate certificates from `fullchain.pem`, allowing clients to verify Let's Encrypt chains correctly
|
|
14
|
+
|
|
15
|
+
## [0.1.2] - 2026-05-23
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Added TLS verification coverage for multiplayer connection settings and certificate trust handling
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Added visible remote shot tracer effects during PvP and Wavesfight multiplayer matches
|
|
24
|
+
- Enabled TLS certificate chain and hostname verification for multiplayer client connections
|
|
25
|
+
- Added support for `TERMFRONT_TLS_CERT_FILE` and `TERMFRONT_TLS_KEY_FILE` when loading the server certificate
|
|
26
|
+
|
|
9
27
|
## [0.1.1] - 2026-05-21
|
|
10
28
|
|
|
11
29
|
### Changed
|
data/README.md
CHANGED
|
@@ -54,6 +54,14 @@ Start a PvP server:
|
|
|
54
54
|
termfront-server
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
Use custom TLS certificate paths:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
TERMFRONT_TLS_CERT_FILE=/path/to/fullchain.pem \
|
|
61
|
+
TERMFRONT_TLS_KEY_FILE=/path/to/privkey.pem \
|
|
62
|
+
termfront-server
|
|
63
|
+
```
|
|
64
|
+
|
|
57
65
|
Use a custom port:
|
|
58
66
|
|
|
59
67
|
```bash
|
|
@@ -110,7 +118,7 @@ Wavesfight is a PvE survival mode built on selected campaign maps.
|
|
|
110
118
|
PvP is currently marked experimental.
|
|
111
119
|
|
|
112
120
|
- The server listens on TCP and wraps traffic with TLS.
|
|
113
|
-
- The client connects directly to `host:port
|
|
121
|
+
- The client connects directly to `host:port` and verifies the server certificate and hostname.
|
|
114
122
|
- The default multiplayer endpoint is `termfront.gamelinks007.net:443`.
|
|
115
123
|
- Matchmaking now supports `1v1`, `2v2`, and `4v4`.
|
|
116
124
|
- Players choose the match size on the client, and the server keeps separate queues for each mode.
|
|
@@ -336,6 +336,7 @@ module Termfront
|
|
|
336
336
|
remote[:current].health = msg[:h]
|
|
337
337
|
remote[:current].weapon = msg[:w]&.to_sym
|
|
338
338
|
remote[:current].ammo = msg[:am]
|
|
339
|
+
spawn_remote_projectile_effect(msg) if (remote[:current].fire_flash || 0) <= 0 && (msg[:ff] || 0) > 0
|
|
339
340
|
remote[:current].fire_flash = msg[:ff] || 0
|
|
340
341
|
remote[:lerp_t] = 0.0
|
|
341
342
|
end
|
|
@@ -377,6 +378,7 @@ module Termfront
|
|
|
377
378
|
|
|
378
379
|
process_fire_pvp if @player.fire_flash == 4
|
|
379
380
|
@player.fire_flash -= 1 if @player.fire_flash > 0
|
|
381
|
+
update_projectile_effects(dt)
|
|
380
382
|
|
|
381
383
|
@player.update_shield(dt, @stdout, audio: @audio)
|
|
382
384
|
|
|
@@ -476,6 +478,7 @@ module Termfront
|
|
|
476
478
|
render_pvp_hud(buf, cols)
|
|
477
479
|
render_view(buf, view_h, view_w, wtop, wbot, wcol)
|
|
478
480
|
render_remote_players_3d(buf, view_h, view_w, virt_h, dists)
|
|
481
|
+
render_pvp_projectiles(buf, view_h, view_w, virt_h, dists)
|
|
479
482
|
buf << "\e[#{3 + view_h};1H"
|
|
480
483
|
render_pvp_radar(buf, cols, radar_h)
|
|
481
484
|
render_crosshair(buf, view_h, view_w, cols)
|
|
@@ -635,6 +638,64 @@ module Termfront
|
|
|
635
638
|
end
|
|
636
639
|
end
|
|
637
640
|
|
|
641
|
+
def render_pvp_projectiles(buf, view_h, view_w, virt_h, dists)
|
|
642
|
+
dx = Math.cos(@player.angle)
|
|
643
|
+
dy = Math.sin(@player.angle)
|
|
644
|
+
px = -dy * Math.tan(Config::FOV / 2.0)
|
|
645
|
+
py = dx * Math.tan(Config::FOV / 2.0)
|
|
646
|
+
inv = 1.0 / (px * dy - py * dx)
|
|
647
|
+
|
|
648
|
+
sprites = []
|
|
649
|
+
@projectiles.each do |projectile|
|
|
650
|
+
ex = projectile[:x] - @player.x
|
|
651
|
+
ey = projectile[:y] - @player.y
|
|
652
|
+
tx = inv * (dy * ex - dx * ey)
|
|
653
|
+
tz = inv * (-py * ex + px * ey)
|
|
654
|
+
next if tz < 0.2
|
|
655
|
+
|
|
656
|
+
sprites << [tz, tx, projectile]
|
|
657
|
+
end
|
|
658
|
+
sprites.sort_by! { |sprite| -sprite[0] }
|
|
659
|
+
|
|
660
|
+
sprites.each do |tz, tx, projectile|
|
|
661
|
+
sx = ((view_w / 2.0) * (1 + tx / tz)).to_i
|
|
662
|
+
pw = (4.0 / tz).ceil.clamp(1, 5)
|
|
663
|
+
ph = (virt_h / tz * 0.15).ceil.clamp(2, 6)
|
|
664
|
+
vmid = virt_h / 2
|
|
665
|
+
draw_top = [(vmid - ph / 2), 0].max
|
|
666
|
+
draw_bot = [(vmid + ph / 2).clamp(draw_top + 2, virt_h), virt_h].min
|
|
667
|
+
start_x = [sx - pw / 2, 0].max
|
|
668
|
+
end_x = [sx + pw / 2, view_w - 1].min
|
|
669
|
+
|
|
670
|
+
start_x.upto(end_x) do |c|
|
|
671
|
+
next if c < 0 || c >= view_w
|
|
672
|
+
next if dists[c] < tz
|
|
673
|
+
|
|
674
|
+
r_top = (draw_top / 2.0).ceil
|
|
675
|
+
r_bot = [(draw_bot / 2.0).floor, r_top + 1].max
|
|
676
|
+
r_top.upto(r_bot - 1) do |r|
|
|
677
|
+
next if r < 0 || r >= view_h
|
|
678
|
+
|
|
679
|
+
vp0 = r * 2
|
|
680
|
+
vp1 = r * 2 + 1
|
|
681
|
+
top_in = vp0 >= draw_top && vp0 < draw_bot
|
|
682
|
+
bot_in = vp1 >= draw_top && vp1 < draw_bot
|
|
683
|
+
next unless top_in || bot_in
|
|
684
|
+
|
|
685
|
+
proj_color = projectile[:color]
|
|
686
|
+
buf << "\e[#{3 + r};#{c + 1}H"
|
|
687
|
+
buf << if top_in && bot_in
|
|
688
|
+
"\e[38;2;#{proj_color}m\xE2\x96\x88\e[0m"
|
|
689
|
+
elsif top_in
|
|
690
|
+
"\e[38;2;#{proj_color}m\xE2\x96\x80\e[0m"
|
|
691
|
+
else
|
|
692
|
+
"\e[38;2;#{proj_color}m\xE2\x96\x84\e[0m"
|
|
693
|
+
end
|
|
694
|
+
end
|
|
695
|
+
end
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
|
|
638
699
|
def tint_player_color(color, mode)
|
|
639
700
|
return nil unless color
|
|
640
701
|
return color if mode == :ally
|
|
@@ -822,6 +883,30 @@ module Termfront
|
|
|
822
883
|
STDIN.raw { |s| s.getc }
|
|
823
884
|
end
|
|
824
885
|
|
|
886
|
+
def spawn_remote_projectile_effect(msg)
|
|
887
|
+
shock = msg[:w].to_s.start_with?("shock")
|
|
888
|
+
color = shock ? "80;220;255" : "255;210;80"
|
|
889
|
+
speed = shock ? 18.0 : 14.0
|
|
890
|
+
angle = msg[:a]
|
|
891
|
+
@projectiles << {
|
|
892
|
+
x: msg[:x],
|
|
893
|
+
y: msg[:y],
|
|
894
|
+
vx: Math.cos(angle) * speed,
|
|
895
|
+
vy: Math.sin(angle) * speed,
|
|
896
|
+
ttl: 0.18,
|
|
897
|
+
color: color
|
|
898
|
+
}
|
|
899
|
+
end
|
|
900
|
+
|
|
901
|
+
def update_projectile_effects(dt)
|
|
902
|
+
@projectiles.reject! do |projectile|
|
|
903
|
+
projectile[:x] += projectile[:vx] * dt
|
|
904
|
+
projectile[:y] += projectile[:vy] * dt
|
|
905
|
+
projectile[:ttl] -= dt
|
|
906
|
+
projectile[:ttl] <= 0 || @map.wall_at?(projectile[:x], projectile[:y])
|
|
907
|
+
end
|
|
908
|
+
end
|
|
909
|
+
|
|
825
910
|
def notify_death_if_needed
|
|
826
911
|
return unless @player.dead
|
|
827
912
|
return if @sent_dead
|
|
@@ -3,29 +3,47 @@
|
|
|
3
3
|
require "socket"
|
|
4
4
|
require "openssl"
|
|
5
5
|
require "json"
|
|
6
|
+
require "time"
|
|
6
7
|
|
|
7
8
|
module Termfront
|
|
8
9
|
module Network
|
|
9
10
|
class Connection
|
|
11
|
+
PeerInfo = Struct.new(
|
|
12
|
+
:certificate_sha256,
|
|
13
|
+
:public_key_sha256,
|
|
14
|
+
:subject,
|
|
15
|
+
:issuer,
|
|
16
|
+
:not_after,
|
|
17
|
+
keyword_init: true
|
|
18
|
+
)
|
|
19
|
+
|
|
10
20
|
attr_reader :rtt
|
|
21
|
+
attr_reader :peer_info
|
|
11
22
|
|
|
12
23
|
def initialize
|
|
13
24
|
@sock = nil
|
|
14
25
|
@buf = +""
|
|
15
26
|
@ping_ts = 0
|
|
16
27
|
@rtt = 0
|
|
28
|
+
@peer_info = nil
|
|
17
29
|
end
|
|
18
30
|
|
|
19
|
-
def connect(host, port)
|
|
31
|
+
def connect(host, port, ca_file: nil)
|
|
20
32
|
tcp = TCPSocket.new(host, port)
|
|
21
33
|
tcp.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
|
22
34
|
|
|
23
|
-
ctx =
|
|
24
|
-
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
35
|
+
ctx = build_ssl_context(ca_file: ca_file)
|
|
25
36
|
@sock = OpenSSL::SSL::SSLSocket.new(tcp, ctx)
|
|
26
37
|
@sock.hostname = host if @sock.respond_to?(:hostname=)
|
|
27
38
|
@sock.sync = true
|
|
28
39
|
@sock.connect
|
|
40
|
+
@sock.post_connection_check(host)
|
|
41
|
+
@peer_info = build_peer_info(@sock.peer_cert)
|
|
42
|
+
rescue StandardError
|
|
43
|
+
tcp&.close
|
|
44
|
+
@sock = nil
|
|
45
|
+
@peer_info = nil
|
|
46
|
+
raise
|
|
29
47
|
end
|
|
30
48
|
|
|
31
49
|
def send_msg(hash)
|
|
@@ -76,6 +94,7 @@ module Termfront
|
|
|
76
94
|
nil
|
|
77
95
|
end
|
|
78
96
|
@sock = nil
|
|
97
|
+
@peer_info = nil
|
|
79
98
|
end
|
|
80
99
|
|
|
81
100
|
def connected?
|
|
@@ -96,6 +115,31 @@ module Termfront
|
|
|
96
115
|
def clock
|
|
97
116
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
98
117
|
end
|
|
118
|
+
|
|
119
|
+
def build_ssl_context(ca_file:)
|
|
120
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
|
121
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
122
|
+
ctx.verify_hostname = true if ctx.respond_to?(:verify_hostname=)
|
|
123
|
+
ctx.cert_store = build_cert_store(ca_file: ca_file)
|
|
124
|
+
ctx
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def build_cert_store(ca_file:)
|
|
128
|
+
store = OpenSSL::X509::Store.new
|
|
129
|
+
store.set_default_paths
|
|
130
|
+
store.add_file(ca_file) if ca_file
|
|
131
|
+
store
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def build_peer_info(cert)
|
|
135
|
+
PeerInfo.new(
|
|
136
|
+
certificate_sha256: OpenSSL::Digest::SHA256.hexdigest(cert.to_der),
|
|
137
|
+
public_key_sha256: OpenSSL::Digest::SHA256.hexdigest(cert.public_key.to_der),
|
|
138
|
+
subject: cert.subject.to_s,
|
|
139
|
+
issuer: cert.issuer.to_s,
|
|
140
|
+
not_after: cert.not_after.utc
|
|
141
|
+
)
|
|
142
|
+
end
|
|
99
143
|
end
|
|
100
144
|
end
|
|
101
145
|
end
|
|
@@ -43,11 +43,12 @@ module Termfront
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def run
|
|
46
|
-
cert, key = load_or_create_cert
|
|
46
|
+
cert, key, chain = load_or_create_cert
|
|
47
47
|
|
|
48
48
|
ctx = OpenSSL::SSL::SSLContext.new
|
|
49
49
|
ctx.cert = cert
|
|
50
50
|
ctx.key = key
|
|
51
|
+
ctx.extra_chain_cert = chain unless chain.empty?
|
|
51
52
|
|
|
52
53
|
tcp_server = TCPServer.new("0.0.0.0", @port)
|
|
53
54
|
ssl_server = OpenSSL::SSL::SSLServer.new(tcp_server, ctx)
|
|
@@ -589,11 +590,14 @@ module Termfront
|
|
|
589
590
|
end
|
|
590
591
|
|
|
591
592
|
def load_or_create_cert
|
|
592
|
-
cert_file = "termfront_server.crt"
|
|
593
|
-
key_file = "termfront_server.key"
|
|
593
|
+
cert_file = ENV.fetch("TERMFRONT_TLS_CERT_FILE", "termfront_server.crt")
|
|
594
|
+
key_file = ENV.fetch("TERMFRONT_TLS_KEY_FILE", "termfront_server.key")
|
|
594
595
|
|
|
595
596
|
if File.exist?(cert_file) && File.exist?(key_file)
|
|
596
|
-
|
|
597
|
+
certs = OpenSSL::X509::Certificate.load(File.read(cert_file))
|
|
598
|
+
certs = [certs] unless certs.is_a?(Array)
|
|
599
|
+
cert = certs.first
|
|
600
|
+
chain = certs.drop(1)
|
|
597
601
|
key = OpenSSL::PKey::RSA.new(File.read(key_file))
|
|
598
602
|
puts "Loaded existing certificate."
|
|
599
603
|
else
|
|
@@ -601,8 +605,9 @@ module Termfront
|
|
|
601
605
|
File.write(cert_file, cert.to_pem)
|
|
602
606
|
File.write(key_file, key.to_pem)
|
|
603
607
|
puts "Generated new self-signed certificate."
|
|
608
|
+
chain = []
|
|
604
609
|
end
|
|
605
|
-
[cert, key]
|
|
610
|
+
[cert, key, chain]
|
|
606
611
|
end
|
|
607
612
|
|
|
608
613
|
def pvp_spawns
|
data/lib/termfront/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,119 +1,119 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: termfront
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
|
|
7
|
+
- S-H-GAMELINKS
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
|
-
description:
|
|
12
|
+
description: A terminal-based first-person shooter with DDA raycasting, campaign mode,
|
|
13
|
+
and PvP multiplayer.
|
|
13
14
|
email:
|
|
14
|
-
|
|
15
|
+
- gamelinks007@gmail.com
|
|
15
16
|
executables:
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
- termfront
|
|
18
|
+
- termfront-server
|
|
18
19
|
extensions: []
|
|
19
20
|
extra_rdoc_files: []
|
|
20
21
|
files:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
22
|
+
- ".ruby-version"
|
|
23
|
+
- CHANGELOG.md
|
|
24
|
+
- LICENSE
|
|
25
|
+
- LICENSE.txt
|
|
26
|
+
- README.md
|
|
27
|
+
- Rakefile
|
|
28
|
+
- data/audio/THIRD_PARTY_NOTICES.md
|
|
29
|
+
- data/audio/beep_02.ogg
|
|
30
|
+
- data/audio/button1.ogg
|
|
31
|
+
- data/audio/complete.ogg
|
|
32
|
+
- data/audio/manifest.json
|
|
33
|
+
- data/audio/mission_bgm.wav
|
|
34
|
+
- data/audio/mission_clear_se.wav
|
|
35
|
+
- data/audio/on.ogg
|
|
36
|
+
- data/audio/page_se.wav
|
|
37
|
+
- data/audio/sector.mp3
|
|
38
|
+
- data/audio/sfx_22b.ogg
|
|
39
|
+
- data/audio/shield_alarm_se.wav
|
|
40
|
+
- data/audio/shield_regen_se.wav
|
|
41
|
+
- data/audio/shoot_01.ogg
|
|
42
|
+
- data/audio/terminal_se.wav
|
|
43
|
+
- data/audio/title.mp3
|
|
44
|
+
- data/audio/title_bgm.wav
|
|
45
|
+
- data/audio/victory.mp3
|
|
46
|
+
- data/events/corridor_sweep.json
|
|
47
|
+
- data/events/final_push.json
|
|
48
|
+
- data/events/stronghold.json
|
|
49
|
+
- data/events/the_gauntlet.json
|
|
50
|
+
- data/events/training_grounds.json
|
|
51
|
+
- exe/termfront
|
|
52
|
+
- exe/termfront-server
|
|
53
|
+
- lib/termfront.rb
|
|
54
|
+
- lib/termfront/audio_manager.rb
|
|
55
|
+
- lib/termfront/config.rb
|
|
56
|
+
- lib/termfront/demo_player.rb
|
|
57
|
+
- lib/termfront/drop_item/base.rb
|
|
58
|
+
- lib/termfront/drop_item/weapon.rb
|
|
59
|
+
- lib/termfront/enemy/base.rb
|
|
60
|
+
- lib/termfront/enemy/crawler.rb
|
|
61
|
+
- lib/termfront/enemy/executor.rb
|
|
62
|
+
- lib/termfront/game.rb
|
|
63
|
+
- lib/termfront/input.rb
|
|
64
|
+
- lib/termfront/map.rb
|
|
65
|
+
- lib/termfront/mission/base.rb
|
|
66
|
+
- lib/termfront/mission/corridor_sweep.rb
|
|
67
|
+
- lib/termfront/mission/event_loader.rb
|
|
68
|
+
- lib/termfront/mission/event_runtime.rb
|
|
69
|
+
- lib/termfront/mission/final_push.rb
|
|
70
|
+
- lib/termfront/mission/stronghold.rb
|
|
71
|
+
- lib/termfront/mission/the_gauntlet.rb
|
|
72
|
+
- lib/termfront/mission/training.rb
|
|
73
|
+
- lib/termfront/mission/training_grounds.rb
|
|
74
|
+
- lib/termfront/network/client.rb
|
|
75
|
+
- lib/termfront/network/connection.rb
|
|
76
|
+
- lib/termfront/network/server.rb
|
|
77
|
+
- lib/termfront/network/wavesfight_client.rb
|
|
78
|
+
- lib/termfront/opponent.rb
|
|
79
|
+
- lib/termfront/player.rb
|
|
80
|
+
- lib/termfront/projectile.rb
|
|
81
|
+
- lib/termfront/remote_enemy.rb
|
|
82
|
+
- lib/termfront/renderer.rb
|
|
83
|
+
- lib/termfront/scene_player.rb
|
|
84
|
+
- lib/termfront/sprite.rb
|
|
85
|
+
- lib/termfront/terminal_output.rb
|
|
86
|
+
- lib/termfront/title_screen.rb
|
|
87
|
+
- lib/termfront/version.rb
|
|
88
|
+
- lib/termfront/weapon/assault_rifle.rb
|
|
89
|
+
- lib/termfront/weapon/base.rb
|
|
90
|
+
- lib/termfront/weapon/pistol.rb
|
|
91
|
+
- lib/termfront/weapon/shock_pistol.rb
|
|
92
|
+
- lib/termfront/weapon/shock_rifle.rb
|
|
93
|
+
- sig/termfront.rbs
|
|
94
|
+
homepage: https://github.com/S-H-GAMELINKS/termfront
|
|
93
95
|
licenses:
|
|
94
|
-
|
|
96
|
+
- MIT
|
|
95
97
|
metadata:
|
|
96
|
-
allowed_push_host:
|
|
97
|
-
homepage_uri:
|
|
98
|
-
source_code_uri:
|
|
99
|
-
changelog_uri:
|
|
98
|
+
allowed_push_host: https://rubygems.org
|
|
99
|
+
homepage_uri: https://github.com/S-H-GAMELINKS/termfront
|
|
100
|
+
source_code_uri: https://github.com/S-H-GAMELINKS/termfront
|
|
101
|
+
changelog_uri: https://github.com/S-H-GAMELINKS/termfront/blob/main/CHANGELOG.md
|
|
100
102
|
rdoc_options: []
|
|
101
103
|
require_paths:
|
|
102
|
-
|
|
104
|
+
- lib
|
|
103
105
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
106
|
requirements:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
version: 3.2.0
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 3.2.0
|
|
109
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
111
|
requirements:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
version: "0"
|
|
112
|
+
- - ">="
|
|
113
|
+
- !ruby/object:Gem::Version
|
|
114
|
+
version: '0'
|
|
115
115
|
requirements: []
|
|
116
|
-
rubygems_version: 4.
|
|
116
|
+
rubygems_version: 4.0.10
|
|
117
117
|
specification_version: 4
|
|
118
118
|
summary: Terminal FPS game with raycasting engine
|
|
119
119
|
test_files: []
|