Skip to content

Commit 4e9b3a9

Browse files
author
minecraft server
committed
Lots of debugging. Added new plugin usercolours, player commands, proper tell().
Changed around import order so proxy.py has one instance. Sigh.
1 parent 313aa94 commit 4e9b3a9

File tree

9 files changed

+198
-114
lines changed

9 files changed

+198
-114
lines changed

config.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import os
1+
import os, sys
2+
3+
DEBUG = 'debug' in sys.argv
24

35
# Info for proxy
4-
LISTEN_ADDR = ('0.0.0.0', 25565)
6+
LISTEN_ADDR = ('0.0.0.0', 25565) if not DEBUG else ('0.0.0.0', 25564)
57
SERVER_ADDR = ('127.0.0.1', 25042)
6-
LOG_FILE = '/var/minecraft/logs/proxy.log'
7-
PLUGIN_PATH = '/var/minecraft/Proxy2/plugins'
8+
LOG_FILE = '/var/minecraft/logs/proxy.log' if not DEBUG else '/var/minecraft/logs/proxy-debug.log'
9+
PLUGIN_PATH = '/var/minecraft/Proxy2/plugins' if not DEBUG else './plugins'
810

911
# Buff sizes - shouldn't change
1012
MAX_SEND = 4096

helpers.py

+31-12
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# -*- coding: cp1252 -*-
22
"""Helper functions for plugins"""
33

4-
import os
5-
from proxy import send_packet
6-
from proxy import server_cmd as cmd
4+
import os, sys
75
from packet_decoder import names as packet_names
6+
from packet_decoder import Packet, SERVER_TO_CLIENT
87
from config import *
98

109
def ops():
@@ -13,6 +12,15 @@ def ops():
1312
ret = [unicode(name) for name in ret]
1413
return ret
1514

15+
def server_cmd(command):
16+
"""Send a command to server console. May OSError."""
17+
p = Popen([COMMAND_SCRIPT, command], stderr=PIPE)
18+
ret = p.wait()
19+
if ret:
20+
out, err = p.communicate()
21+
raise OSError(command, ret, err.read().strip())
22+
return
23+
1624
colors = {
1725
'black': u'0',
1826
'dark blue': u'1',
@@ -33,18 +41,25 @@ def ops():
3341
}
3442
def color(name):
3543
"""Takes a color name and returns the string needed to turn the chat message that color."""
36-
if name not in color_map:
44+
if name not in colors:
3745
raise ValueError('Bad color %s' % repr(name))
38-
return u'§' + color_map[name]
46+
return u'§' + colors[name]
47+
48+
49+
def all_users():
50+
"""Returns list of users who ever played on the server"""
51+
return [name[:-4] for name in os.listdir(os.path.join(WORLD_DIR, 'players'))]
3952

4053

4154
locks = set()
42-
def tell(user, message, delay=0, lock=None):
55+
def tell(user, message, delay=0, lock=None, prefix=''):
4356
"""Send a server message to user.
57+
Note: Splits multiline messages. See prefix, below.
4458
Optional args:
4559
delay: Wait delay seconds before sending message. Useful mainly with lock. See below.
4660
lock: Until message sent (see delay) allow no new messages with the same user and lock value.
4761
Generally speaking, expected to be a string. But it doesn't really matter.
62+
prefix: Add given prefix to every line sent, eg '<server>: '.
4863
Returns bool of whether message was sent (see lock)
4964
"""
5065
global locks
@@ -53,13 +68,17 @@ def tell(user, message, delay=0, lock=None):
5368
return False
5469
else:
5570
locks.add((user, lock))
71+
message = unicode(message)
5672
def tell_send():
57-
packet = Packet()
58-
packet.ident = packet_names['Chat message']
59-
packet.direction = CLIENT_TO_SERVER if to_server else SERVER_TO_CLIENT
60-
packet.data = {'text': unicode(message)}
61-
send_packet(packet, user, False)
62-
locks.remove((user, lock))
73+
reverse = dict([(y,x) for x,y in packet_names.items()])
74+
for line in message.split('\n'):
75+
packet = Packet()
76+
packet.ident = reverse['Chat message']
77+
packet.direction = SERVER_TO_CLIENT
78+
packet.data = {'text': line}
79+
send_packet(packet, user, False)
80+
if lock is not None:
81+
locks.remove((user, lock))
6382

6483
if delay:
6584
schedule(tell_send, delay)

killproxy

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
#!/bin/bash
22

3-
{ ps aux | grep 'python proxy\.py' | grep -v grep | awk '{print $2}' | xargs kill 2>/dev/null ; } &&
3+
if [ "$1" == "debug" ]; then
4+
name="python proxy\.py debug"
5+
else
6+
name="python proxy\.py"
7+
fi
8+
9+
{ ps aux | grep "$name" | grep -v grep | awk '{print $2}' | xargs kill 2>/dev/null ; } &&
410
echo "Killed proxy"

plugins.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33
sys.path.append(PLUGIN_PATH)
44

55
# Import plugins here
6-
import log_all, log_sorted, usernames, no_changes, sp_opcolor
6+
import log_all, log_sorted, usernames, no_changes, sp_opcolor, usercolors, bad_cmd
7+
import player_cmd as cmd
78

89
# Set ordering here
9-
plugins = [log_all, log_sorted, usernames, sp_opcolor]
10+
plugins = []
11+
plugins.append(log_sorted) # Always first to catch all raw packets
12+
plugins.append(usernames) # The earlier the better, name the login packets sooner.
13+
plugins.append(cmd) # Should probably be before anything that depends on it
14+
plugins.append(usercolors)
15+
plugins.append(bad_cmd) # Always last out of chat commands

plugins/bad_cmd.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Simple plugin to catch bad commands and report them. Should be loaded last."""
2+
3+
import player_cmd as cmd
4+
from helpers import tell
5+
6+
def on_start():
7+
cmd.register(r'/(.*)', uncaught_command)
8+
9+
def on_packet(packet, user, to_server):
10+
return packet
11+
12+
def uncaught_command(message, user, command):
13+
tell(user, "Bad command: %s" % command)

plugins/cmd.py plugins/player_cmd.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
Modules shoud register a regex to match a chat message exactly.
66
Along with this regex is a callback function that has args: (message, user, *regex_groups)
77
and returns False to let packet pass through or True to drop it.
8+
If None is returned, defaults to dropping it.
89
This behaviour is intended to allow further checking before deciding if the packet should be dropped.
910
Messages are passed through all matching functions (unless dropped)
1011
in the order of regsitration (shich should occur during on_start()).
1112
"""
1213

13-
from packet_decoder import names as packet_names
1414
import re
1515

1616
registrations = [] # List of (regex obj, function)
@@ -23,15 +23,16 @@ def on_start():
2323
def on_packet(packet, user, to_server):
2424
global registrations
2525

26-
if not to_server or packet.ident != packet_names['Chat message']:
26+
if not to_server or packet.name() != 'Chat message':
2727
return packet
2828

2929
message = packet.data['text']
3030

3131
for regex, func in registrations:
3232
match = regex.match(message)
3333
if match is not None:
34-
if not func(message, user, *match.groups):
34+
ret = func(message, user, *match.groups())
35+
if ret is None or ret:
3536
break # break skips the else and so returns [] immediately
3637
else: # runs only if break is never reached, ie. no dropping matches.
3738
return packet
@@ -53,6 +54,6 @@ def on_start():
5354
cmd.register('/msg ([^ ]+) (.*)', private_msg)
5455
"""
5556
global registrations
56-
regex = r'(?:%s)$' # Make match end of string also
57+
regex = r'(?:%s)$' % regex # Make match end of string also
5758
regex = re.compile(regex)
5859
registrations.append((regex, func))

plugins/usercolors.py

+81-50
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,81 @@
1-
2-
AUTHOR="ekimekim (based on sleepyparadox's 'sp_opcolor')"
3-
4-
DESCRIPTION= """A plugin that highlights usernames in chat.
5-
Has different colours for ops, logged in users, not logged in users, and yourself.
6-
Colours have sensible defaults but are configurable with in-game commands:
7-
/colors help
8-
/colors TYPE COLOR
9-
"""
10-
11-
from packet_decoder import Packet
12-
from helpers import ops, color
13-
14-
opColor = color('red')
15-
userColor = color('dark cyan')
16-
17-
def on_start():
18-
cmd.register('/color (.*)', on_command)
19-
20-
def on_packet(packet, user, to_server):
21-
if packet.name() == 'Chat message':
22-
#Highlight admin names in red
23-
if not to_server:
24-
for op in ops():
25-
#insert op color flag before name and normal color flag after name
26-
packet.data['text'] = packet.data['text'].replace(op, opColor + op + color('white'))
27-
packet.data['text'] = packet.data['text'].replace(user.username, userColor + user.username + color('white'))
28-
29-
#replace 'bitblitz' with developer name 'Sleepy Paradox'
30-
packet.data['text'] = packet.data['text'].replace(u'bitblitz', u'Sleepy Paradox')
31-
#return edited packet
32-
return packet
33-
34-
HELP = """Chat color commands:
35-
/color help - This message
36-
/color colors - List available colors
37-
/color all X - set all chat messages to X
38-
/color active X - set logged in usernames to X
39-
/color inactive X - set logged out usernames to X
40-
/color me X - set yourself to appear as X
41-
___Note: Only you see the new color, not everyone.
42-
/color ops X - set ops to appear as X
43-
Replace X with the color you want, as given by /color colors."""
44-
45-
def on_command(message, user, command):
46-
verb, value = command.split(' ', 1)
47-
if verb == 'help':
48-
user.tell(HELP)
49-
elif verb in user.setcolors:
50-
if value in color.colors
1+
2+
AUTHOR="ekimekim (based on sleepyparadox's 'sp_opcolor')"
3+
4+
DESCRIPTION= """A plugin that highlights usernames in chat.
5+
Has different colours for ops, logged in users, not logged in users, and yourself.
6+
Colours have sensible defaults but are configurable with in-game commands:
7+
/colors help
8+
/colors TYPE COLOR
9+
"""
10+
11+
from packet_decoder import Packet
12+
from helpers import ops, color, colors, all_users, active_users, tell
13+
import player_cmd as cmd
14+
15+
defaults = {
16+
'all': color('white'),
17+
'inactive': color('dark gray'),
18+
'active': color('gray'),
19+
'ops': color('red'),
20+
'me': color('dark cyan')
21+
}
22+
23+
users = {}
24+
25+
def on_start():
26+
cmd.register('/color (.*)', on_command)
27+
cmd.register('/color ?', no_command)
28+
29+
def on_packet(packet, user_obj, to_server):
30+
if packet.name() == 'Chat message' and not to_server:
31+
prefs = users.get(user_obj.username, defaults)
32+
offlines = dict([(user, prefs['inactive']) for user in all_users()])
33+
onlines = dict([(user, prefs['active']) for user in active_users()])
34+
ops_dict = dict([(user, prefs['ops']) for user in ops()])
35+
player = {user_obj.username: prefs['me']}
36+
names = {}
37+
names.update(offlines)
38+
names.update(onlines)
39+
names.update(ops_dict)
40+
names.update(player)
41+
packet.data['text'] = prefs['all'] + packet.data['text']
42+
for name in names:
43+
packet.data['text'] = packet.data['text'].replace(name, names[name] + name + prefs['all'])
44+
return packet
45+
46+
HELP = """Chat color commands:
47+
/color help - This message
48+
/color colors - List available colors
49+
/color all X - set all chat messages to X
50+
/color active X - set logged in usernames to X
51+
/color inactive X - set logged out usernames to X
52+
/color me X - set yourself to appear as X
53+
___Note: Only you see the new color, not everyone.
54+
/color ops X - set ops to appear as X
55+
Replace X with the color you want, as given by /color colors."""
56+
57+
def on_command(message, user, command):
58+
parts = command.split(' ', 1)
59+
if len(parts) == 2:
60+
verb, value = parts
61+
else:
62+
verb = parts[0]
63+
if verb == 'help':
64+
tell(user, HELP)
65+
elif verb == 'colors':
66+
for c in colors:
67+
prefs = users.get(user.username, defaults)
68+
tell(user, 'color: %s"%s"%s' % (color(c), c, prefs['all']))
69+
elif verb in defaults:
70+
if value in colors:
71+
prefs = users.get(user.username, defaults.copy())
72+
prefs[verb] = color(value)
73+
users[user.username] = prefs
74+
else:
75+
tell(user, 'color: That is not a valid color!')
76+
else:
77+
tell(user, 'color: Bad command. Try "/color help"')
78+
79+
80+
def no_command(message, user):
81+
tell(user, 'Modify user colors! Type "/color help".')

0 commit comments

Comments
 (0)