Skip to content

Commit 313aa94

Browse files
committed
Merge 192.168.1.7:Projects/mcproxy into prod
2 parents 61de3db + 01942cd commit 313aa94

11 files changed

+251
-40
lines changed

config.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import os
22

33
# Info for proxy
4-
LISTEN_ADDR = ('0.0.0.0', 25564)
5-
SERVER_ADDR = ('127.0.0.1', 25565)
4+
LISTEN_ADDR = ('0.0.0.0', 25565)
5+
SERVER_ADDR = ('127.0.0.1', 25042)
66
LOG_FILE = '/var/minecraft/logs/proxy.log'
77
PLUGIN_PATH = '/var/minecraft/Proxy2/plugins'
88

helpers.py

+58-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,67 @@
1+
# -*- coding: cp1252 -*-
12
"""Helper functions for plugins"""
23

34
import os
4-
5-
65
from proxy import send_packet
76
from proxy import server_cmd as cmd
7+
from packet_decoder import names as packet_names
88
from config import *
99

1010
def ops():
1111
"""Get list of op usernames."""
12-
open(os.path.join(SERVER_DIR, 'ops.txt'))
12+
ret = open(os.path.join(SERVER_DIR, 'ops.txt')).read().strip().split('\n')
13+
ret = [unicode(name) for name in ret]
14+
return ret
15+
16+
colors = {
17+
'black': u'0',
18+
'dark blue': u'1',
19+
'dark green': u'2',
20+
'dark cyan': u'3',
21+
'dark red': u'4',
22+
'purple': u'5',
23+
'gold': u'6',
24+
'gray': u'7',
25+
'dark gray': u'8',
26+
'blue': u'9',
27+
'green': u'a',
28+
'cyan': u'b',
29+
'red': u'c',
30+
'pink': u'd',
31+
'yellow': u'e',
32+
'white': u'f'
33+
}
34+
def color(name):
35+
"""Takes a color name and returns the string needed to turn the chat message that color."""
36+
if name not in color_map:
37+
raise ValueError('Bad color %s' % repr(name))
38+
return u'§' + color_map[name]
39+
40+
41+
locks = set()
42+
def tell(user, message, delay=0, lock=None):
43+
"""Send a server message to user.
44+
Optional args:
45+
delay: Wait delay seconds before sending message. Useful mainly with lock. See below.
46+
lock: Until message sent (see delay) allow no new messages with the same user and lock value.
47+
Generally speaking, expected to be a string. But it doesn't really matter.
48+
Returns bool of whether message was sent (see lock)
49+
"""
50+
global locks
51+
if lock is not None:
52+
if (user, lock) in locks:
53+
return False
54+
else:
55+
locks.add((user, lock))
56+
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))
63+
64+
if delay:
65+
schedule(tell_send, delay)
66+
else:
67+
tell_send()

killproxy

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

3-
ps aux | grep 'python proxy\.py' | grep -v grep | awk '{print $2}' | xargs kill
3+
{ ps aux | grep 'python proxy\.py' | grep -v grep | awk '{print $2}' | xargs kill 2>/dev/null ; } &&
4+
echo "Killed proxy"

packet_decoder.py

+7-30
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import struct
44
import sys
5-
import nbt
65

76
#TODO: Review which of these we actually need
87
NODE_SERVER = 0x01
@@ -541,7 +540,6 @@ def get_struct(self, packet):
541540
o = o[packet.direction]
542541
if len(o) and not isinstance(o[0], tuple):
543542
o = (o),
544-
#print o
545543
return o
546544

547545

@@ -562,18 +560,14 @@ def pack(self, data_type, data):
562560
if nbtdata is None:
563561
o += self.pack('short', -1)
564562
else:
565-
nbtdata = nbt.encode(nbtdata)
566-
nbtdata = nbt.gzip(nbtdata)
567563
nbt_len = len(nbtdata)
568564
o += self.pack('short', nbt_len)
569565
o += nbtdata
570566
return o
571567
if data_type == "metadata":
572568
o = ''
573569
for mtype, val in data:
574-
#print "Packing", mtype, val
575570
mtype2 = mtype >> 5
576-
#print "mtype2 is", mtype2
577571
o += self.pack('byte', mtype)
578572
if mtype2 == 0: o += self.pack('byte', val)
579573
if mtype2 == 1: o += self.pack('short', val)
@@ -626,9 +620,11 @@ def unpack(self, data_type):
626620
if extra_len <= 0:
627621
o["extra"] = None
628622
else:
623+
if len(self.buff) < extra_len:
624+
raise IncompleteData()
629625
extra_buff = self.buff[:extra_len]
630626
self.buff = self.buff[extra_len:]
631-
o["extra"] = nbt.decode(nbt.gunzip(self.buff))
627+
o["extra"] = extra_buff
632628
return o
633629
if data_type == "metadata":
634630
#[(17, 0), (0, 0), (16, -1)]
@@ -704,7 +700,7 @@ def read_packet(self):
704700
"""
705701

706702
#self.debug("READ BUFFER SIZE: %d" % len(self.buff))
707-
backup = self.buff
703+
backup = self.buff[:]
708704
packet = Packet()
709705
try:
710706
packet.direction = self.node
@@ -763,7 +759,7 @@ def read_packet(self):
763759
if packet.ident == 0x82:
764760
packet.data["text"] = []
765761
for i in range(4):
766-
packet.data["text"].append(packet.data.pop("line_%s" % (i+1)))
762+
packet.data["text"].append(packet.data["line_%s" % (i+1)])
767763

768764
#0x83
769765
if packet.ident == 0x83:
@@ -779,7 +775,9 @@ def read_packet(self):
779775
self.buff = backup
780776
return None
781777
except Exception, ex:
778+
self.buff = backup
782779
ex.args += (self.buff[20:],)
780+
raise
783781

784782

785783
def encode_packet(self, packet):
@@ -829,7 +827,6 @@ def encode_packet(self, packet):
829827
if packet.ident == 0x82:
830828
for i in range(4):
831829
packet.data["line_%s" % (i+1)] = packet.data["text"][i]
832-
del packet.data["text"]
833830
#0x83
834831
if packet.ident == 0x83:
835832
packet.data['data_size'] = len(packet.data['data'])
@@ -839,26 +836,6 @@ def encode_packet(self, packet):
839836
output += self.pack(i[0], packet.data[i[1]])
840837

841838
output += append
842-
# Is this meant to be a multiline comment? Seriously?
843-
"""
844-
if hasattr(packet, "original") and output != packet.original:
845-
f1 = open('err1.bin', 'w')
846-
f1.write(packet.original)
847-
f1.close()
848-
f2 = open('err2.bin', 'w')
849-
f2.write(output)
850-
f2.close()
851-
self.debug("Packet mis-match!")
852-
self.debug("ID: %x" % packet.ident)
853-
print packet.data
854-
sys.exit(1)"""
855-
"""if len(output) != len(packet.original):
856-
print "%x\tXX %i\t%i" % (packet.ident, len(packet.original), len(output))
857-
print "APPEND: %i" % len(append)
858-
print packet.data
859-
else:
860-
print "OK"
861-
print "%x\tOK %i\t%i" % (packet.ident, len(packet.original), len(output))"""
862839
return output
863840
except:
864841
raise

plugins.py

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

55
# Import plugins here
6-
import log_all, log_sorted, usernames, no_changes
6+
import log_all, log_sorted, usernames, no_changes, sp_opcolor
77

88
# Set ordering here
9-
plugins = [log_all, log_sorted, usernames, no_changes]
9+
plugins = [log_all, log_sorted, usernames, sp_opcolor]

plugins/cmd.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
AUTHOR = 'ekimekim'
3+
CONTACT = '[email protected]'
4+
DESCRIPTION = """A module intended to be a single module for command-like chat triggers.
5+
Modules shoud register a regex to match a chat message exactly.
6+
Along with this regex is a callback function that has args: (message, user, *regex_groups)
7+
and returns False to let packet pass through or True to drop it.
8+
This behaviour is intended to allow further checking before deciding if the packet should be dropped.
9+
Messages are passed through all matching functions (unless dropped)
10+
in the order of regsitration (shich should occur during on_start()).
11+
"""
12+
13+
from packet_decoder import names as packet_names
14+
import re
15+
16+
registrations = [] # List of (regex obj, function)
17+
18+
19+
def on_start():
20+
pass
21+
22+
23+
def on_packet(packet, user, to_server):
24+
global registrations
25+
26+
if not to_server or packet.ident != packet_names['Chat message']:
27+
return packet
28+
29+
message = packet.data['text']
30+
31+
for regex, func in registrations:
32+
match = regex.match(message)
33+
if match is not None:
34+
if not func(message, user, *match.groups):
35+
break # break skips the else and so returns [] immediately
36+
else: # runs only if break is never reached, ie. no dropping matches.
37+
return packet
38+
return []
39+
40+
41+
def register(regex, func):
42+
"""Register a callback function to be called when a chat message matches regex.
43+
regex should be a valid regular expression that matches against the whole chat message.
44+
func should take args (message, user, *regex_groups) and return False
45+
to pass packet along or True to drop it.
46+
regex_groups are the groups returned by a regex match (as per re.match(regex).groups)
47+
Example:
48+
def private_msg(message, user, target, priv_msg):
49+
# sends target the message priv_msg
50+
return True # drop packet
51+
52+
def on_start():
53+
cmd.register('/msg ([^ ]+) (.*)', private_msg)
54+
"""
55+
global registrations
56+
regex = r'(?:%s)$' # Make match end of string also
57+
regex = re.compile(regex)
58+
registrations.append((regex, func))

plugins/no_changes.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Note this is a lengthy operation and should be used sparingly."""
33

44
import packet_decoder
5+
import simple_logging as logging
56

67
def on_start():
78
pass
@@ -11,4 +12,7 @@ def on_packet(packet, user, to_server):
1112
reencoded = packet_decoder.stateless_pack(packet, to_server)
1213
if packet.original != reencoded:
1314
raise Exception("Packet (%s) changed: Reencodes to %s, not %s" % (packet, repr(reencoded), repr(packet.original)))
14-
return packet
15+
else:
16+
logging.debug('Packet without original')
17+
logging.debug("Packet of type %s" % packet.name())
18+
return packet

plugins/sp_opcolor.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
AUTHOR='sleepyparadox'
3+
4+
DESCRIPTION= """Sleepy Paradox - Op Color
5+
A simple plugin that highlights the developers efforts.
6+
Highlights 'Sleepy Paradox' and ekimekim' in red.
7+
Also replaces 'bitblitz' with 'Sleepy Paradox' (To make account consistent with developer name)"""
8+
9+
from packet_decoder import Packet
10+
from helpers import ops, color
11+
12+
opColor = color('red')
13+
userColor = color('dark cyan')
14+
15+
def on_start():
16+
pass
17+
18+
def on_packet(packet, user, to_server):
19+
if packet.name() == 'Chat message':
20+
#Highlight admin names in red
21+
if not to_server:
22+
for op in ops():
23+
#insert op color flag before name and normal color flag after name
24+
packet.data['text'] = packet.data['text'].replace(op, opColor + op + color('white'))
25+
packet.data['text'] = packet.data['text'].replace(user.username, userColor + user.username + color('white'))
26+
27+
#replace 'bitblitz' with developer name 'Sleepy Paradox'
28+
packet.data['text'] = packet.data['text'].replace(u'bitblitz', u'Sleepy Paradox')
29+
#return edited packet
30+
return packet

plugins/usercolors.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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

0 commit comments

Comments
 (0)