Beispiel #1
0
def zonemodify(message, user, zone, key, value):
	if name not in zones.get_zones():
		tell(user, "Zone does not exist.")
		return
	zone = zones.get_zones()[zone]
	zone[key] = eval(value)
	tell(user, "Success")
Beispiel #2
0
def from_cube_pt2(user, value, name, point1):
	try:
		point2 = get_point(user, value)
	except ValueError:
		return from_cube_pt1(user, ",".join([str(x) for x in point1]), name)
	tell(user, "Set second point at (%.2f,%.2f,%.2f)" % tuple(point2))
	return make_zone(user, name, ('cube', user.dimension, point1, point2))
Beispiel #3
0
def aclset(message, user, zone, name, perms):
	perms = filter(None, perms.split()) if perms is not None else []
	for perm in perms:
		if perm not in ALL_PERMS:
			tell(user, "%s not an ACL." % perm)
			return
	zone['acls'][name] = perms
	tell(user, "Success")
Beispiel #4
0
def from_cyl_height(user, value, name, point, radius):
	try:
		height = float(value)
		if height <= 0:
			raise ValueError()
	except ValueError:
		tell(user, "%s not a valid positive number." % value)
		return from_cyl_radius(user, str(radius), name, point)
	tell(user, "Set height as %.2f" % height)
	return make_zone(user, name, ('cylinder', user.dimension, point, radius, height))
Beispiel #5
0
def aclhelp(message, user):
	tell(user, "ACLs are my equivilent of plot protection.\n"
	           "A zone (see /zone help) has permissions for different "
	           "users to do different things. The creator of a zone can change these. "
	           "The permissions available are:\n"
	           "ENTRY - Without this permission, you can't enter the zone.\n"
	           "INTERACT - Without this permission, you can't flip levers, open doors, etc. "
	           "Note: even with this permission, you need to not be holding a block in your hands for it to work.\n"
	           "MODIFY - Without this permission, you can't place or dig blocks.\n"
	           "ADMIN - This permission allows you to change the permissions of this zone.\n"
	           "Type /acls commands for help on how to modify permissions."
	           "Type /acls op for help on op-only commands.")
Beispiel #6
0
def zonehere(message, user):
	flag = False
	for zone in user.zones:
		if 'acls' in zone:
			perms = zone['acls'].get(user.username, zone['acls']['EVERYONE'])
			perms = ": " + " ".join(perms)
		else:
			perms = ""
		tell(user, zone['name'] + perms)
		flag = True
	if not flag:
		tell(user, "In no zones.")
Beispiel #7
0
def ophelp(message, user):
	tell(user, "Note that unlike /zone commands, zone names are taken verbatim (no quotes).\n"
	           "/zone op help - Obvious.\n"
	           "/zone op wool <zone> - 10x10x10 cube below player highlighted as follows:\n"
	           "__ green: In given zone.\n"
	           "__ yellow: In zone besides one given.\n"
	           "__ red: In given zone AND at least one other.\n"
	           "__ You will need to log out/in to reverse changes.\n"
	           "/wool - Shortcut to re-run last wool command.\n"
	           "/zone op wool-all <zone> - Does wool for an entire zone.\n"
	           "/zone op confirm <zone> - Confirm zone.\n"
	           '/zone op modify "<zone>" <key> <value> - Advanced use. Quotes required.')
Beispiel #8
0
def zonewool(message, user, name):
	user.morewool = name
	try:
		zone = zones.get_zones()[name]
	except KeyError:
		tell(user, "Bad zone name")
		return
	base = [int(axis) for axis in user.position]
	for x in range(base[0]-5, base[0]+5):
		for y in range(base[1]-10, base[1]):
			for z in range(base[2]-5, base[2]+5):
				wool_point(zone, user, (x,y,z))
	tell(user, "Complete.")
Beispiel #9
0
def helplist(message, user):
	tell(user, "The /zone commands let you manage your zones.\n"
	           "In all commands below, <zone> should be replaced with\n"
	           "the name of a zone you control, eg. /zone view my_zone\n"
	           "If the name has a space in it, put it in double quotes.\n"
	           "/zone current - See a list of zones you control that you are currently in.\n"
	           "/zone view - See a list of zones you control.\n"
	           "/zone view <zone> - Get info on that zone.\n"
	           "/zone here - Get list of zones you are currently in, and your permissions.\n"
	           "/zone new - Create new zone using menu system.\n"
	           "/zone new <zone> <args> - Advanced only, see help page.\n"
	           "/zone destroy <zone> - Delete a zone permanently.\n"
	           "/zone help <command> - Get help on a command, eg. /zone help new\n")
Beispiel #10
0
def zonewoolall(message, user, name):
	yield
	EDGE = 4 # extra blocks beyond edges
	user.morewool = name
	try:
		zone = zones.get_zones()[name]
	except KeyError:
		tell(user, "Bad zone name")
		return
	if zone['bounds_info'][0] == 'cube':
		box = zone['bounds_info'][2:]
		box = zip(*box)
		box = [sorted(axis) for axis in box]
	elif zone['bounds_info'][0] == 'cylinder':
		(x, y, z), r, h = zone['bounds_info'][2:]
		box = ((x-r, x+r), (y, y+h), (z-r, z+r))
	else:
		tell(user, "Unsupported zone type: %s" % zone['bounds_info'][0])
		return
	box = [(int(a)-EDGE, int(b)+1+EDGE) for a,b in box]
	for y in range(*box[1]):
		for x in range(*box[0]):
			yield
			for z in range(*box[2]):
				wool_point(zone, user, (x,y,z))
		complete = float(y-box[1][0])/(box[1][1]-box[1][0])
		if complete < 1:
			tell(user, 'Wooling %s...%.2f%% complete' % (name, 100 * complete))
	tell(user, 'Complete.')
Beispiel #11
0
def get_point(user, value):
	if not value:
		x,y,z = user.position
		return (x, y, z)
	try:
		point = [float(x.strip()) for x in value.split(',')]
	except ValueError:
		point = []
	if len(point) != 3:
		tell(user, "Badly formatted response. For example,\n"
		           "the point at x=100, y=64, z=-100 would be typed as\n"
		           ":100,64,-100")
		raise ValueError
	return point
Beispiel #12
0
def from_name(user, name):
	if name in get_zones():
		tell(user, "That name is already in use.")
		return ROOT_MENU

	return (
		"The new zone will be called %s.\n"
		"Please pick a basic shape for the new zone.\n" % name,
		[
			("Cube", lambda u,v: from_cube(u, v, name)),
			("Cylinder", lambda u,v: from_cyl(u, v, name))
		],
		exit_menu
	)
Beispiel #13
0
def from_cyl_radius(user, value, name, point):
	try:
		radius = float(value)
		if radius <= 0:
			raise ValueError()
	except ValueError:
		tell(user, "%s not a valid positive number." % value)
		return from_cyl_pt(user, ",".join([str(x) for x in point]), name)
	return (
		"Set radius as %.2f\n"
		"Please give the zone height (how far up from the base point)." % radius,
		('prompt', lambda u,v: from_cyl_height(u, v, name, point, radius)),
		exit_menu
	)
Beispiel #14
0
	def wrapped_fn(message, user, zone, name, *args):

		zone_original = zone
		zone = zone.strip('"')
		if zone not in get_zones():
			tell(user, "Zone does not exist.")
			print zone
			return
		zone = get_zones()[zone]
		if 'acls' not in zone:
			tell(user, "Sorry, that zone does not appear to support ACLs.\n"
			           "You may need to contact an op to resolve this.")
			return

		if name != 'EVERYONE':
			name = name.lower()
			if name not in all_users() and name not in zone['acls']:
				tell(user, "Warning: %s is not a player known to this server.\n"
				           "If you have made a mistake, type:\n/acls %s clear %s" % (zone_original, name))

		if ADMIN not in zone['acls'].get(user.username, zone['acls']['EVERYONE']) and user.username not in ops():
			tell(user, "You do not have permission to modify ACLs for this zone. "
			           "If you have accidentially locked yourself out, please contact an op for assistance.")
			return

		return fn(message, user, zone, name, *args)
Beispiel #15
0
def aclcmdhelp(message, user):
	tell(user, "ACL commands:\n"
	           "/acls <zone> set <user> <permissions>\n"
	           "__ Set the user's permissions in that zone to exactly\n"
	           "__ the permissions given. Permissions should be\n"
	           "__ space-seperated, eg. ENTRY INTERACT MODIFY\n"
	           "__ Leave it blank to set all permissions off.\n"
	           "/acls <zone> add <user> <permission>\n"
	           "__ Add a single permission to what a user can do.\n"
	           "/acls <zone> remove <user> <permission>\n"
	           "__ Remove a single permission from what a user can do.\n"
	           "/acls <zone> clear <user>\n"
	           "__ Reset the given user to use the default permissions.\n"
	           "To modify the default permissions, replace <user> with EVERYONE.")
Beispiel #16
0
def on_packet(packet, user, to_server):
	if not to_server:
		return packet

	# ENTRY
	if packet.name() in ('Player position', 'Player position & look') and not check_acls(ENTRY, user):
		tell(user, "You are not allowed to enter here.", delay=0.2, lock=("acl-entry-lock",user))
		new_stance = packet.data['stance'] - packet.data['y'] + user.position_old[1]
		packet.data['x'], packet.data['y'], packet.data['z'] = user.position_old
		packet.data['stance'] = new_stance
		back_packet = Packet()
		back_packet.ident = 0x0B # Player position
		back_packet.direction = SERVER_TO_CLIENT
		back_packet.data['x'] = packet.data['x']
		back_packet.data['y'] = packet.data['y']
		back_packet.data['z'] = packet.data['z']
		back_packet.data['stance'] = packet.data['stance']
		back_packet.data['on_ground'] = packet.data['on_ground']
		send_packet(back_packet, user, False)
		return packet

	# MODIFY (block digging)
	if packet.name() == 'Player digging' and packet.data['status'] == 0:
		position = (packet.data['x'], packet.data['y'], packet.data['z'])
		if not check_acls(MODIFY, user, position):
			tell(user, "You are not allowed to dig here.")
			return []

	# MODIFY/INTERACT (block placement)
	if packet.name() == 'Player block placement' and not all(packet.data[key] == -1 for key in ('x','y','z','direction')):
		position = add_direction((packet.data['x'], packet.data['y'], packet.data['z']), packet.data['direction'])
		if packet.data['slot']['id'] in INTERACT_IDS:
			if not check_acls(INTERACT, user, position):
				tell(user, "You are not allowed to interact with things here.")
				return []
		else:
			if not check_acls(MODIFY, user, position):
				tell(user, "You are not allowed to place blocks here.")

				# For now, we tell the client that the block in the indicated direction is empty.
				# This should work almost all the time and is by far the easiest option.
				back_packet = Packet()
				back_packet.ident = 0x35 # Block change
				back_packet.direction = SERVER_TO_CLIENT
				back_packet.data['x'], back_packet.data['y'], back_packet.data['z'] = position
				back_packet.data['id'] = 0
				back_packet.data['metadata'] = 0
				send_packet(back_packet, user, False)

				# We also invalidate the packet rather than drop it, so the server auto-corrects the client's inventory
				packet.data['x'] += 100

	return packet
Beispiel #17
0
def make_zone(user, name, bounds_info):
	zone = new_zone(name, bounds_info, user.username, confirmed=False)
	if zone is None:
		tell(user, "An error occurred while creating the zone. Try again or call an op.")
	else:
		tell(user, "Zone %s created. Exiting menu." % name)
		if user in ops():
			zone['confirmed'] = True
			tell(user, "Zone auto-confirmed for ops.")
		else:
			tell(user, "You will need to get your zone approved by an op\n"
			           "for plot protection to work.")
Beispiel #18
0
def helpinfo(message, user, command):
	helptext = {
		'view': "If no zone given, shows a list of zone names.\n"
		        "If a zone name given (and you have ADMIN rights to it),"
		        "displays a bunch of information about the zone.\n"
		        "Not all this info is likely to be useful, but oh well.",
		'here': "List all zones that you are currently standing in.\n"
		        "Also gives what permissions you are allowed in that zone.\n",
		'destroy': "Delete a zone and all associated information.\n"
		           "This includes any plot protection the zone may have provided.\n"
		           "No, ops cannot undo this. Use only if you are really sure.",
		'new': "When used with nothing else given, ie. just /zone new, "
		       "opens menu that will make a new zone step by step.\n"
		       "For advanced use, give the zone name followed by bounds args.\n"
		       "Bounds definitions are one of the following:\n"
		       "__ cube <dim> <x1> <y1> <z1> <x2> <y2> <z2>\n"
		       "__ cylinder <dim> <x> <y> <z> <radius> <height>\n"
		       "__ json <json> (EXPERIMENTAL, MAY NOT WORK)\n"
		       "Note that <dim> should be 0,-1,1 for overworld, Nether, End\n"
		       "The json bounds defn is special. The remainder of the line "
		       "should be valid JSON. If you don't know what that is, ignore it. JSON schema "
		       "is given by typing /zone help json",
		'help': "Ha ha, you're really funny. If you're reading this\n"
		        "you know how to use the help function already, moron.",
		'json': "In these definitions, we use the syntax <name:type> or just <type>.\n"
		        "point := [<x:float>, <y:float>, <z:float>]\n"
		        "bounds_info :=\n"
		        "__ ['cube', <dim:int>, <point1:point>, <point2:point>] OR\n"
		        "__ ['cylinder', <dim:int>, <base:point>, <radius:float>,\n"
		        "____ <height:float>] OR\n"
		        "__ ['union', <bounds_info>, <bounds_info>, ...]\n"
		        "For example, the following describes a zone that covers both a cylinder "
		        "in Overworld and a cube in the Nether:\n"
		        "['union', ['cylinder', 0, [128,64,-128], 8, 64], \n"
		        "__ ['cube', -1, [64,64,-64], [80,128,-80]]]"
	}

	if command not in helptext:
		tell(user, "Unknown command: %s" % command)
	else:
		tell(user, helptext[command])
Beispiel #19
0
	def tell_bounds(style, *args, **kwargs):
		indent = kwargs.pop("indent",0)
		indent_str = "__" * indent
		if style == 'cube':
			dim, point1, point2 = args
			tell(user, indent_str + "Cube in dim%d%s from (%.2f,%.2f,%.2f) to (%.2f,%.2f,%.2f)" % ((dim, dim_to_name(dim)) + tuple(point1) + tuple(point2)))
		elif style == 'cylinder':
			dim, base, radius, height = args
			tell(user, indent_str + "Cylinder in dim%d%s from (%.2f,%.2f,%.2f) to radius %.2f and height %.2f" % ((dim, dim_to_name(dim)) + tuple(base) + (radius, height)))
		elif style == 'union':
			tell(user, indent_str + "Union of regions:")
			for more_info in args:
				tell_bounds(*more_info, indent=indent+1)
		else:
			tell(user, indent_str + "Unknown region")
Beispiel #20
0
def acladd(message, user, zone, name, perm):
	if perm not in ALL_PERMS:
		tell(user, "%s not an ACL." % perm)
	current = zone['acls'].setdefault(name, zone['acls']['EVERYONE'][:])
	if perm in current:
		tell(user, "%s can already %s" % (name, perm))
	else:
		current.append(perm)
		tell(user, "Success")
Beispiel #21
0
def aclclear(message, user, zone, name):
	if name == 'EVERYONE':
		tell(user, "EVERYONE is not valid for this command")
		return
	if name not in zone['acls']:
		tell(user, "%s doesn't have any specific ACLs" % name)
	else:
		zone['acls'].pop(name)
		tell(user, "Success")
Beispiel #22
0
def aclrm(message, user, zone, name, perm):
	if perm not in ALL_PERMS:
		tell(user, "%s not an ACL." % perm)
	current = zone['acls'].setdefault(name, zone['acls']['EVERYONE'][:])
	if perm not in current:
		tell(user, "%s already can't %s" % (name, perm))
	else:
		current.remove(perm)
		tell(user, "Success")
Beispiel #23
0
def zonedestroy(message, user, name):
	name = name.strip('"')

	try:
		zone = get_zones()[name]
	except KeyError:
		tell(user, "That zone doesn't exist!")
		return
	if not controls_zone(user.username, zone) and not user.username in ops():
		tell(user, "That isn't your zone.")
	get_zones().pop(name)
	tell(user, "Zone deleted.")
Beispiel #24
0
def zoneinfo(message, user, name):
	name = name.strip('"')

	try:
		zone = get_zones()[name]
	except KeyError:
		tell(user, "That zone doesn't exist!")
		return
	if not controls_zone(user.username, zone) and not user.username in ops():
		tell(user, "That isn't your zone.")
		return

	keys = ['name','creator','confirmed']
	for key in keys:
		if key in zone:
			tell(user, "%s: %s" % (key, zone[key]))

	keys.append('bounds_info')
	def dim_to_name(dim):
		try:
			return {-1: '(Nether)', 0: '(Overworld)', 1:'(End)'}[dim]
		except KeyError:
			return ""
	def tell_bounds(style, *args, **kwargs):
		indent = kwargs.pop("indent",0)
		indent_str = "__" * indent
		if style == 'cube':
			dim, point1, point2 = args
			tell(user, indent_str + "Cube in dim%d%s from (%.2f,%.2f,%.2f) to (%.2f,%.2f,%.2f)" % ((dim, dim_to_name(dim)) + tuple(point1) + tuple(point2)))
		elif style == 'cylinder':
			dim, base, radius, height = args
			tell(user, indent_str + "Cylinder in dim%d%s from (%.2f,%.2f,%.2f) to radius %.2f and height %.2f" % ((dim, dim_to_name(dim)) + tuple(base) + (radius, height)))
		elif style == 'union':
			tell(user, indent_str + "Union of regions:")
			for more_info in args:
				tell_bounds(*more_info, indent=indent+1)
		else:
			tell(user, indent_str + "Unknown region")
	tell_bounds(*zone['bounds_info'])

	if 'acls' in zone:
		keys.append('acls')
		tell(user, "acls:")
		for name in zone['acls']:
			if name == 'EVERYONE':
				continue
			tell(user, "__%s: %s" % (name, ",".join(zone['acls'][name])))
		tell(user, "__Everyone else: %s" % ",".join(zone['acls']['EVERYONE']))

	for key in zone:
		if key in keys:
			continue
		tell(user, "%s: %s" % (key, zone[key]))
Beispiel #25
0
def opforce(message, user, mode):
	user.acl_force = (mode == 'on')
	tell(user, "Set force %s" % mode)
Beispiel #26
0
def zonelist(message, user):
	for zone in get_zones().values():
		if controls_zone(user.username, zone):
			tell(user, zone['name'] + (" (unconfirmed)" if not zone.get('confirmed',True) else ""))
Beispiel #27
0
def start_menu(message, user):
	try:
		display(user, *ROOT_MENU)
	except MenuLockError:
		tell(user, "You already have a menu open.\nTry :again to see it or :exit to quit it.")
Beispiel #28
0
def exit_menu(user, value):
	tell(user, "Zone creation cancelled")
Beispiel #29
0
def zonenew(message, user, name, args):
	name = name.strip('"')

	if name in get_zones():
		tell(user, "Name already taken.")
		return

	if args.startswith("json "):
		try:
			data = loads(args[5:])
		except Exception:
			tell(user, "Bad json.")
			return

		def validate_point(data):
			if type(data) != list:
				raise ValueError()
			if len(data) != 3:
				raise ValueError()
			if not all(type(x) in (int, float) for x in data):
				raise ValueError()

		def validate_info(data):
			if type(data) != list:
				raise ValueError()
			style = data[0]
			if style == 'cube':
				dim, point1, point2 = data[1:]
				if type(dim) != int or dim not in (-1,0,1):
					raise ValueError()
				validate_point(point1)
				validate_point(point2)
			elif style == 'cylinder':
				dim, base, radius, height = data[1:]
				if type(dim) != int or dim not in (-1,0,1):
					raise ValueError()
				if not validate_point(base):
					raise ValueError()
				if type(radius) not in (int, float) or radius <= 0:
					raise ValueError()
				if type(height) not in (int, float) or height <= 0:
					raise ValueError()
			elif style == 'union':
				[validate_info(x) for x in data[1:]]
			else:
				raise ValueError()

		try:
			validate_info(data)
		except ValueError:
			tell(user, "Invalid JSON, see /help json for schema.")
			return

		zone = new_zone(name, data, user.username)

	else:
		args = filter(None, args.split())
		style = args.pop(0)
		try:
			dim = int(args.pop(0))
			if dim not in (-1,0,1):
				raise ValueError()
			args = [float(arg) for arg in args]
			if style == 'cube':
				if len(args) != 6:
					raise ValueError()
				point1 = args[:3]
				point2 = args[3:]
				zone = new_zone(name, ('cube',dim,point1,point2), user.username)
			elif style == 'cylinder':
				if len(args) != 5:
					raise ValueError()
				base = args[:3]
				radius, height = args[3:]
				if radius <= 0 or height <= 0:
					raise ValueError()
				zone = new_zone(name, ('cylinder',dim,base,radius,height), user.username)
			else:
				raise ValueError			
		except ValueError:
			tell(user, "Bad args.")
			return

	if zone is None:
		tell(user, "Unknown error while creating zone")
	else:
		tell(user, "Success. Remember that you still need an op to confirm the zone.")
Beispiel #30
0
def zoneconfirm(message, user, name):
	if name not in zones.get_zones():
		tell(user, "Zone does not exist.")
		return
	zones.get_zones()[name]['confirmed'] = True
	tell(user, "Success")