gamefic-mud 0.0.1 → 1.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1a8fbce2090194a364d012ad04c933a9c1ff572f
4
- data.tar.gz: 31c1ff56b98dd54c820092872fb379f92224c6e8
2
+ SHA256:
3
+ metadata.gz: ff2aa9c86a961ebb613299ee247dc201b473c7659c4a035546e4143f0a35b863
4
+ data.tar.gz: 5abc56417d93af1c3dea919e90614672eb4f920024971f52235487399194f2d0
5
5
  SHA512:
6
- metadata.gz: 8b4ff2794d6b3aeb5e52c700635c7c72efee2e5f01f3d57ef0e3b12e3b76ea8734a0c532afd2b61d833c3b0647d5f8aa563e2f8951f4d5aa261b705b7fbfaf47
7
- data.tar.gz: 2307f17548a756283f15571eab5c04da03e268ce4d86df59fd74b65a029fdd02bb858b8dc3b15f804a5988249265bf795fefc39de162f347a971a9a0001ef62a
6
+ metadata.gz: cb8514110747d8d4d8df20c48e0c6685bc2a6b8961dbdc47c0439fd668c0a8dd75f55eb01e70a847681cc667a01c46ca75f40117f5483e2fa1e14dd3028a0ccd
7
+ data.tar.gz: b5ecc5b4e032a94298c17d9e198883182be82881ecaa5001d7ab6aaa730301b75671347437f813e551c94a7b525e10fa7fdf432374088dda1c2bda020a9f6944
data/lib/gamefic-mud.rb CHANGED
@@ -1,8 +1,9 @@
1
- module Gamefic
2
-
3
- module Mud
4
- autoload :Engine, 'gamefic-mud/engine'
5
- autoload :User, 'gamefic-mud/user'
6
- end
7
-
8
- end
1
+ require 'gamefic'
2
+
3
+ module Gamefic
4
+ module Mud
5
+ autoload :Adapter, 'gamefic-mud/adapter'
6
+ autoload :Engine, 'gamefic-mud/engine'
7
+ autoload :State, 'gamefic-mud/state'
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Gamefic
2
+ module Mud
3
+ module Adapter
4
+ autoload :Common, 'gamefic-mud/adapter/common'
5
+ autoload :Tcp, 'gamefic-mud/adapter/tcp'
6
+ autoload :Websocket, 'gamefic-mud/adapter/websocket'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,60 @@
1
+ module Gamefic
2
+ module Mud
3
+ module Adapter
4
+ # Common attributes and methods of client adapters.
5
+ #
6
+ module Common
7
+ # @return [Plot]
8
+ attr_accessor :plot
9
+
10
+ # @return [Actor]
11
+ attr_accessor :character
12
+
13
+ # @return [State::Base]
14
+ attr_reader :state
15
+
16
+ # @param state [Class<State::Base>]
17
+ # @return [void]
18
+ def start state
19
+ @state = state.new(self)
20
+ @state.start
21
+ end
22
+
23
+ def session
24
+ @session ||= {}
25
+ end
26
+
27
+ def [] key
28
+ session[key]
29
+ end
30
+
31
+ def []= key, value
32
+ session[key] = value
33
+ end
34
+
35
+ # @!method send_raw(data)
36
+ # Send raw data to the client outside of the game.
37
+ # Normally, game-related data is sent through the character,
38
+ # usually via `character#tell` or `character#stream`. `#raw_data`
39
+ # allows the engine to communicate with the client outside of the
40
+ # game proper, e.g., to display a login prompt.
41
+ #
42
+ # Adapters should implement this method.
43
+ #
44
+ # @abstract
45
+ # @param data [String] The message text
46
+ # @return [void]
47
+
48
+ # @!method update(output)
49
+ # Send a game update to the client. The engine uses this method to
50
+ # broadcast messages and provide data about the current game state.
51
+ #
52
+ # Adapters should implement this method.
53
+ #
54
+ # @abstract
55
+ # @param output [Hash]
56
+ # @return [void]
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,61 @@
1
+ require 'html_to_ansi'
2
+ require 'socket'
3
+
4
+ module Gamefic
5
+ module Mud
6
+ module Adapter
7
+ # The TCP client adapter module.
8
+ #
9
+ module Tcp
10
+ include Common
11
+
12
+ # @return [String]
13
+ attr_reader :ip_addr
14
+
15
+ # @return [Integer]
16
+ attr_reader :port
17
+
18
+ def post_init
19
+ port, ip = Socket.unpack_sockaddr_in(get_peername)
20
+ @port = port
21
+ @ip_addr = ip
22
+ puts "Connection received from #{ip}:#{port}"
23
+ end
24
+
25
+ def receive_data data
26
+ state.process data
27
+ end
28
+
29
+ def update output
30
+ # TCP connections are assumed to be terminal clients. Convert messages and options into
31
+ # an HTML block and convert it to ANSI text.
32
+ text = output[:messages]
33
+ unless output[:options].nil?
34
+ list = '<ol>'
35
+ state[:options].each do |o|
36
+ list += "<li>#{o}</li>"
37
+ end
38
+ list += "</ol>"
39
+ text += list
40
+ end
41
+ # @todo The line endings should probably be a function of HtmlToAnsi.
42
+ send_data HtmlToAnsi.convert(text).gsub(/\n/, "\r\n")
43
+ end
44
+
45
+ def send_raw data
46
+ send_data data
47
+ end
48
+
49
+ def receive_data data
50
+ state.process data.to_s.strip
51
+ end
52
+
53
+ def unbind
54
+ puts "Disconnecting from #{ip_addr}:#{port}"
55
+ # @todo Right way to remove player from game?
56
+ plot.destroy character unless character.nil?
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,30 @@
1
+ require 'json'
2
+
3
+ module Gamefic
4
+ module Mud
5
+ module Adapter
6
+ # The WebSocket client adapter module.
7
+ #
8
+ module Websocket
9
+ include Common
10
+
11
+ # @param output [Hash]
12
+ # @return [void]
13
+ def update output
14
+ # Websocket connections are assumed to be rich clients. Send them
15
+ # the entire output hash and let them determine how to render the
16
+ # data.
17
+ send output.to_json
18
+ end
19
+
20
+ # @param data [String]
21
+ # @return [void]
22
+ def send_raw data
23
+ # Convert raw text to a hash with a `messages` key so the WebSocket
24
+ # client can rely on a single standard for incoming data.
25
+ update({messages: data})
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,146 +1,129 @@
1
- require 'websocket-eventmachine-server'
2
-
3
- module Gamefic
4
-
5
- class Mud::Engine < Gamefic::Engine::Base
6
- def post_initialize
7
- @web_connections = {}
8
- @accepts = []
9
- end
10
-
11
- def will_accept type: :tcpsocket, host: '0.0.0.0', port: 4342
12
- @accepts.push({ type: type, host: host, port: port })
13
- end
14
-
15
- def will_accept_tcpsocket host: '0.0.0.0', port: 4342
16
- will_accept type: :tcpsocket, host: host, port: port
17
- end
18
-
19
- def will_accept_websocket host: '0.0.0.0', port: 4343
20
- will_accept type: :websocket, host: host, port: port
21
- end
22
-
23
- def run
24
- EM.epoll
25
- EM.run do
26
- trap("TERM") { stop }
27
- trap("INT") { stop }
28
-
29
- if @accepts.empty?
30
- will_accept
31
- end
32
- @accepts.each { |a|
33
- if a[:type] == :websocket
34
- start_websocket host: a[:host], port: a[:port]
35
- else
36
- start_tcpsocket host: a[:host], port: a[:port]
37
- end
38
- }
39
-
40
- EventMachine.add_periodic_timer 1 do
41
- plot.ready
42
- plot.update
43
- plot.players.each { |p|
44
- data = p.user.flush
45
- if data != ''
46
- p.user.update data
47
- p.user.prompt p.prompt
48
- end
49
- }
50
- end
51
- end
52
-
53
- end
54
-
55
- def stop
56
- puts "Terminating WebSocket Server"
57
- EventMachine.stop
58
- end
59
-
60
- private
61
-
62
- def start_websocket host:, port:
63
- ::WebSocket::EventMachine::Server.start(host: host, port: port) do |ws|
64
-
65
- ws.onopen do
66
- puts "Client connected"
67
- user = Gamefic::Mud::User::WebSocket.new(ws, self)
68
- user.start Mud::User::State::Login
69
- @web_connections[ws] = user
70
- end
71
-
72
- ws.onmessage do |msg, type|
73
- @web_connections[ws].process msg
74
- end
75
-
76
- ws.onclose do
77
- puts "Client disconnected"
78
- plot.destroy @web_connections[ws].character unless @web_connections[ws].character.nil?
79
- @web_connections.delete ws
80
- end
81
-
82
- ws.onerror do |e|
83
- puts "Error: #{e}"
84
- end
85
-
86
- ws.onping do |msg|
87
- puts "Received ping: #{msg}"
88
- end
89
-
90
- ws.onpong do |msg|
91
- puts "Received pong: #{msg}"
92
- end
93
-
94
- end
95
-
96
- puts "WebSocket server started on #{host}:#{port}"
97
- end
98
-
99
- module TcpHandler
100
- attr_accessor :plot
101
- attr_accessor :user
102
- attr_reader :ip_addr
103
- attr_reader :port
104
-
105
- def post_init
106
- port, ip = Socket.unpack_sockaddr_in(get_peername)
107
- @port = port
108
- @ip_addr = ip
109
- puts "Connection received from #{ip}:#{port}"
110
- end
111
-
112
- def receive_data data
113
- # HACK Convert to UTF-8 and close connection on errors
114
- conv = ''
115
- data.each_byte { |b|
116
- c = b.chr.encode('UTF-8')
117
- if c.valid_encoding?
118
- conv += c
119
- else
120
- conv += '?'
121
- end
122
- }
123
- conv.strip!
124
- user.process conv
125
- rescue Encoding::UndefinedConversionError
126
- puts 'Throwing away garbage'
127
- close_connection
128
- end
129
- def unbind
130
- puts "Disconnecting from #{ip_addr}:#{port}"
131
- plot.destroy user.character unless user.character.nil?
132
- end
133
- end
134
-
135
- def start_tcpsocket host:, port:
136
- EventMachine.start_server host, port, TcpHandler do |conn|
137
- conn.plot = plot
138
- conn.user = Gamefic::Mud::User::TcpSocket.new(conn, self)
139
- conn.user.start Mud::User::State::Login
140
- end
141
-
142
- puts "Telnet server started on #{host}:#{port}"
143
- end
144
- end
145
-
146
- end
1
+ require 'eventmachine'
2
+ require 'em-websocket'
3
+
4
+ module Gamefic
5
+ module Mud
6
+ # The MUD server engine. Responsible for handling client connections and
7
+ # updating the game state.
8
+ #
9
+ class Engine
10
+ # @return [Plot]
11
+ attr_reader :plot
12
+
13
+ # @param plot [Plot] The game plot
14
+ # @param start [Class<State::Base>] The initial state for new connections
15
+ # @param interval [Numeric] The number of seconds between updates
16
+ def initialize plot, start: State::Guest, interval: 1
17
+ @plot = plot
18
+ @start = start
19
+ @interval = interval
20
+ @web_connections = {}
21
+ @accepts = []
22
+ @connections = []
23
+ end
24
+
25
+ # Tell the engine to run a TCP or WebSocket server.
26
+ #
27
+ # @param type [Symbol] :tcpsocket or :websocket
28
+ # @param host [String] The host name
29
+ # @param port [Integer] The port number
30
+ # @return [void]
31
+ def will_accept type: :tcpsocket, host: '0.0.0.0', port: 4342
32
+ @accepts.push({ type: type, host: host, port: port })
33
+ end
34
+
35
+ # Tell the engine to run a TCP server.
36
+ #
37
+ # @param host [String] The host name
38
+ # @param port [Integer] The port number
39
+ # @return [void]
40
+ def will_accept_tcpsocket host: '0.0.0.0', port: 4342
41
+ will_accept type: :tcpsocket, host: host, port: port
42
+ end
43
+
44
+ # Tell the engine to run a WebSocket server.
45
+ #
46
+ # @param host [String] The host name
47
+ # @param port [Integer] The port number
48
+ # @return [void]
49
+ def will_accept_websocket host: '0.0.0.0', port: 4343
50
+ will_accept type: :websocket, host: host, port: port
51
+ end
52
+
53
+ # Start the engine.
54
+ #
55
+ # @return [void]
56
+ def run
57
+ EM.epoll
58
+ EM.run do
59
+ trap("TERM") { stop }
60
+ trap("INT") { stop }
61
+
62
+ # Start a default TCP server if none are configured
63
+ will_accept if @accepts.empty?
64
+
65
+ @accepts.each do |a|
66
+ if a[:type] == :websocket
67
+ start_websocket host: a[:host], port: a[:port]
68
+ else
69
+ start_tcpsocket host: a[:host], port: a[:port]
70
+ end
71
+ end
72
+
73
+ EventMachine.add_periodic_timer @interval do
74
+ plot.update
75
+ plot.ready
76
+ @connections.each do |conn|
77
+ next unless conn.character
78
+ conn.update conn.character.output
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def self.start plot, **options
85
+ engine = new(plot, **options)
86
+ yield(engine) if block_given?
87
+ engine.run
88
+ end
89
+
90
+ # Stop the engine.
91
+ #
92
+ # @return [void]
93
+ def stop
94
+ puts "Terminating server"
95
+ EventMachine.stop
96
+ end
97
+
98
+ private
99
+
100
+ def start_websocket host:, port:
101
+ EM::WebSocket.run(host: host, port: port) do |ws|
102
+ ws.onopen do |_handshake|
103
+ ws.extend Adapter::Websocket
104
+ ws.plot = plot
105
+ ws.start @start
106
+ @connections.push ws
107
+ end
108
+
109
+ # WebSocket messages are handled here because using `receive_data` in
110
+ # the adapter raises character encoding errors.
111
+ ws.onmessage do |msg|
112
+ ws.state.process msg.to_s.strip
113
+ end
114
+ end
115
+ puts "WebSocket server started on #{host}:#{port}"
116
+ end
117
+
118
+ def start_tcpsocket host:, port:
119
+ EventMachine.start_server host, port, Adapter::Tcp do |conn|
120
+ conn.plot = plot
121
+ conn.start @start
122
+ @connections.push conn
123
+ end
124
+
125
+ puts "Telnet server started on #{host}:#{port}"
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,9 @@
1
+ module Gamefic
2
+ module Mud
3
+ module State
4
+ autoload :Base, 'gamefic-mud/state/base'
5
+ autoload :Guest, 'gamefic-mud/state/guest'
6
+ autoload :Play, 'gamefic-mud/state/play'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ module Gamefic
2
+ module Mud
3
+ module State
4
+ # An abstract class for handling client states.
5
+ #
6
+ class Base
7
+ # @return [Adapter::Common]
8
+ attr_reader :adapter
9
+
10
+ # @param adapter [Adapter::Common]
11
+ def initialize adapter
12
+ @adapter = adapter
13
+ end
14
+
15
+ # Called when a client's state changes.
16
+ # Subclasses should implement this method.
17
+ #
18
+ # @return [void]
19
+ def start
20
+ puts "User started #{self.class}"
21
+ end
22
+
23
+ # Called when a message is received from a client.
24
+ # Subclasses should implement this method.
25
+ #
26
+ # @param message [String]
27
+ # @return [void]
28
+ def process message
29
+ puts "User sent #{message} in #{self.class}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ module Gamefic
2
+ module Mud
3
+ module State
4
+ # A simple introductory state that creates a character with a name
5
+ # provided by the user. MUDs in production should implement a more
6
+ # robust version of authentication, but this is sufficient for testing
7
+ # and development.
8
+ #
9
+ class Guest < Base
10
+ def start
11
+ adapter.send_raw 'Enter your name: '
12
+ end
13
+
14
+ def process message
15
+ if message.strip.empty?
16
+ adapter.send_raw "Blank names are not allowed.\r\n"
17
+ start
18
+ else
19
+ character = adapter.plot.make_player_character
20
+ character.name = message.strip
21
+ adapter.character = character
22
+ adapter.start Mud::State::Play
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ module Gamefic
2
+ module Mud
3
+ module State
4
+ # The typical gameplay handler. This state processes client messages as
5
+ # commands to be executed by the player's character.
6
+ #
7
+ class Play < Base
8
+ def start
9
+ adapter.plot.introduce adapter.character
10
+ # Since the game is already running when the player connects, the
11
+ # plot update flushes messages received in the introduction. We're
12
+ # working around the problem by sending them here.
13
+ adapter.update({ messages: adapter.character.messages })
14
+ end
15
+
16
+ def process message
17
+ adapter.character.queue.push message unless message == ''
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
- module Gamefic
2
- module Mud
3
- VERSION = '0.0.1'
4
- end
5
- end
1
+ module Gamefic
2
+ module Mud
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
metadata CHANGED
@@ -1,43 +1,105 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gamefic-mud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-06 00:00:00.000000000 Z
11
+ date: 2021-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: em-websocket
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: eventmachine
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: gamefic
15
43
  requirement: !ruby/object:Gem::Requirement
16
44
  requirements:
17
- - - ">="
45
+ - - "~>"
18
46
  - !ruby/object:Gem::Version
19
- version: '0'
47
+ version: '2.1'
20
48
  type: :runtime
21
49
  prerelease: false
22
50
  version_requirements: !ruby/object:Gem::Requirement
23
51
  requirements:
24
- - - ">="
52
+ - - "~>"
25
53
  - !ruby/object:Gem::Version
26
- version: '0'
54
+ version: '2.1'
27
55
  - !ruby/object:Gem::Dependency
28
- name: websocket-eventmachine-server
56
+ name: html_to_ansi
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
59
  - - "~>"
32
60
  - !ruby/object:Gem::Version
33
- version: 1.0.1
61
+ version: '0.1'
34
62
  type: :runtime
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
66
  - - "~>"
39
67
  - !ruby/object:Gem::Version
40
- version: 1.0.1
68
+ version: '0.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.5'
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 3.5.0
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '3.5'
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 3.5.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: simplecov
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.14'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '0.14'
41
103
  description: An engine for running multiplayer games with Gamefic
42
104
  email: fsnyder@gamefic.com
43
105
  executables: []
@@ -45,21 +107,21 @@ extensions: []
45
107
  extra_rdoc_files: []
46
108
  files:
47
109
  - lib/gamefic-mud.rb
110
+ - lib/gamefic-mud/adapter.rb
111
+ - lib/gamefic-mud/adapter/common.rb
112
+ - lib/gamefic-mud/adapter/tcp.rb
113
+ - lib/gamefic-mud/adapter/websocket.rb
48
114
  - lib/gamefic-mud/engine.rb
49
- - lib/gamefic-mud/user.rb
50
- - lib/gamefic-mud/user/base.rb
51
- - lib/gamefic-mud/user/state.rb
52
- - lib/gamefic-mud/user/state/base.rb
53
- - lib/gamefic-mud/user/state/login.rb
54
- - lib/gamefic-mud/user/state/play.rb
55
- - lib/gamefic-mud/user/tcpsocket.rb
56
- - lib/gamefic-mud/user/websocket.rb
115
+ - lib/gamefic-mud/state.rb
116
+ - lib/gamefic-mud/state/base.rb
117
+ - lib/gamefic-mud/state/guest.rb
118
+ - lib/gamefic-mud/state/play.rb
57
119
  - lib/gamefic-mud/version.rb
58
120
  homepage: http://gamefic.com
59
121
  licenses:
60
122
  - MIT
61
123
  metadata: {}
62
- post_install_message:
124
+ post_install_message:
63
125
  rdoc_options: []
64
126
  require_paths:
65
127
  - lib
@@ -74,9 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
136
  - !ruby/object:Gem::Version
75
137
  version: '0'
76
138
  requirements: []
77
- rubyforge_project:
78
- rubygems_version: 2.5.1
79
- signing_key:
139
+ rubygems_version: 3.1.6
140
+ signing_key:
80
141
  specification_version: 4
81
142
  summary: Gamefic MUD
82
143
  test_files: []
@@ -1,10 +0,0 @@
1
- module Gamefic
2
-
3
- module Mud::User
4
- autoload :Base, 'gamefic-mud/user/base'
5
- autoload :State, 'gamefic-mud/user/state'
6
- autoload :WebSocket, 'gamefic-mud/user/websocket'
7
- autoload :TcpSocket, 'gamefic-mud/user/tcpsocket'
8
- end
9
-
10
- end
@@ -1,32 +0,0 @@
1
- module Gamefic
2
-
3
- class Mud::User::Base < Gamefic::User::Base
4
- attr_accessor :character
5
- attr_reader :engine
6
-
7
- def initialize connection, engine
8
- @connection = connection
9
- @engine = engine
10
- @state = Mud::User::State::Base.new(self)
11
- end
12
-
13
- def start user_state
14
- @state = user_state.new(self)
15
- @state.start
16
- end
17
-
18
- def process message
19
- @state.process message
20
- end
21
-
22
- def update data
23
- end
24
-
25
- def transmit data
26
- end
27
-
28
- def prompt text
29
- end
30
- end
31
-
32
- end
@@ -1,9 +0,0 @@
1
- module Gamefic
2
-
3
- module Mud::User::State
4
- autoload :Base, 'gamefic-mud/user/state/base'
5
- autoload :Login, 'gamefic-mud/user/state/login'
6
- autoload :Play, 'gamefic-mud/user/state/play'
7
- end
8
-
9
- end
@@ -1,23 +0,0 @@
1
- module Gamefic
2
-
3
- module Mud::User::State
4
-
5
- class Base
6
- attr_reader :user
7
-
8
- def initialize user
9
- @user ||= user
10
- end
11
-
12
- def start
13
- puts "User started #{self.class}"
14
- end
15
-
16
- def process message
17
- puts "User sent #{message} in #{self.class}"
18
- end
19
-
20
- end
21
-
22
- end
23
- end
@@ -1,21 +0,0 @@
1
- module Gamefic
2
-
3
- module Mud::User::State
4
-
5
- class Login < Base
6
-
7
- def start
8
- user.prompt 'Enter your name:'
9
- end
10
-
11
- def process message
12
- character = user.engine.plot.make Character, name: message, description: "#{message} is your name."
13
- character.connect user
14
- user.character = character
15
- user.transmit "Welcome, #{message}."
16
- user.start Mud::User::State::Play
17
- end
18
- end
19
-
20
- end
21
- end
@@ -1,13 +0,0 @@
1
- module Gamefic
2
-
3
- class Mud::User::State::Play < Mud::User::State::Base
4
- def start
5
- user.engine.plot.introduce user.character
6
- end
7
-
8
- def process message
9
- user.character.queue.push message unless message == ''
10
- end
11
- end
12
-
13
- end
@@ -1,19 +0,0 @@
1
- require 'gamefic/text'
2
-
3
- module Gamefic
4
-
5
- class Mud::User::TcpSocket < Mud::User::Base
6
- def update data
7
- transmit "\n" + Gamefic::Text::Html::Conversions.html_to_ansi(data)
8
- end
9
-
10
- def transmit data
11
- @connection.send_data data
12
- end
13
-
14
- def prompt text
15
- transmit "\n#{text} "
16
- end
17
- end
18
-
19
- end
@@ -1,17 +0,0 @@
1
- module Gamefic
2
-
3
- class Mud::User::WebSocket < Mud::User::Base
4
- def update data
5
- transmit data
6
- end
7
-
8
- def transmit data
9
- @connection.send data
10
- end
11
-
12
- def prompt text
13
- transmit "<label class=\"prompt\">#{text}</label>"
14
- end
15
- end
16
-
17
- end