/* * /bezier - * * Draws a beizer curvee using between user-specified control points. * The curve will pass through the first and last points, but not necessarily * through the rest. * * Permissions: * - command.draw.bezier * Needed to execute the command. */ void c_bezier::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.draw.bezier")) return; if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 2) { this->show_summary (pl); return; } std::string str = reader.next ().as_str (); if (!sutils::is_block (str)) { pl->message ("§c * §7Invalid block§f: §c" + str); return; } blocki bl = sutils::to_block (str); if (bl.id == BT_UNKNOWN) { pl->message ("§c * §7Unknown block§f: §c" + str); return; } int order = 2; if (reader.has_next ()) { command_reader::argument arg = reader.next (); if (!arg.is_int ()) { pl->message ("§c * §7Usage§f: §e/bezier §cblock §8[§corder§8]"); return; } order = arg.as_int (); if (order <= 0 || order > 20) { pl->message ("§c * §7Invalid bezier curve order §f(§7Must be between §b1-20§f)"); return; } } bezier_data *data = new bezier_data (pl->get_world (), bl, order); pl->create_data ("bezier", data, [] (void *ptr) { delete static_cast<bezier_data *> (ptr); }); pl->get_nth_marking_callback (1) += on_blocks_marked; std::ostringstream ss; ss << "§5Draw§f: §3bezier curve §f[§7order§f: §8" << order << "§f, §7block§f: §8" << block_info::from_id (bl.id)->name; if (bl.meta != 0) ss << ':' << (int)bl.meta; ss << "§f]:"; pl->message (ss.str ()); ss.str (std::string ()); ss.clear (); ss << "§7 | §ePlease mark §b" << (order + 1) << " §eblocks§f."; pl->message (ss.str ()); }
static void do_set (player *pl, command_reader& reader) { if (!pl->has ("command.info.money.set")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } else if (reader.arg_count () != 3) { pl->message ("§c * §7Usage§c: §e/money set §cplayer amount"); return; } std::string target_name = reader.next (); double amount = reader.next ().as_float (); std::string colored_target_name; // the easy way player *target = pl->get_server ().get_players ().find (target_name.c_str ()); if (target) { target->bal = amount; colored_target_name.assign (target->get_colored_username ()); } else { // the hard way soci::session sql (pl->get_server ().sql_pool ()); try { if (!sqlops::player_exists (sql, target_name.c_str ())) { pl->message ("§c * §7No such player§f: §c" + target_name); return; } sqlops::set_money (sql, target_name.c_str (), amount); colored_target_name.assign (sqlops::player_colored_name (sql, target_name.c_str (), pl->get_server ())); } catch (const std::exception& ex) { pl->message ("§4 * §cAn error has occurred§4."); return; } } std::ostringstream ss; ss << colored_target_name << "§e's balance has been set to §7$" << utils::format_number (amount, 2); pl->message (ss.str ()); }
static void _handle_regenerate (player *pl, world *w, command_reader& reader) { if (!pl->has ("command.world.world.regenerate")) { pl->message (messages::not_allowed ()); return; } if (reader.arg_count () < 2 || reader.arg_count () > 3) { pl->message ("§c * §7Usage§f: §e/world regenerate §cgenerator §8[§cseed§8]"); return; } const std::string gen_name = reader.next ().as_str (); long long gen_seed = w->get_generator ()->seed (); if (reader.has_next ()) { auto arg = reader.next (); if (!arg.is_int ()) { pl->message ("§c * §7The seed must be an integer§c."); return; } gen_seed = arg.as_int (); } world_generator *gen = world_generator::create (gen_name.c_str (), gen_seed); if (!gen) { pl->message ("§c * §7No such world generator§f: §c" + gen_name); return; } w->set_generator (gen); w->clear_chunks (false, true); w->get_players ().all ( [] (player *pl) { pl->rejoin_world (); pl->message ("§bWorld reloaded"); }); /* std::ostringstream ss; ss << w->get_colored_name () << " §eregenerated §f[§eseed§f: §7" << gen_seed << "§f]"; pl->message (ss.str ()); */ }
static void _handle_reset (player *pl, command_reader& reader) { if (reader.arg_count () != 3) { pl->message ("§c * §7Usage§f: §e/zone reset §czone-name sel-name"); return; } std::string zone_name = reader.next (); if (zone_name.size () < 3 || zone_name[0] != 'z' || zone_name[1] != '@') { pl->message ("§c * §7Invalid zone name§f: §c" + zone_name); return; } zone_name.erase (0, 2); std::string sel_name = reader.next (); if (sel_name.empty () || (sel_name[0] != '@')) { pl->message ("§c * §7Invalid selection name§f: §c" + sel_name); return; } sel_name.erase (0, 1); world *w = pl->get_world (); zone *zn = w->get_zones ().find (zone_name); if (!zn) { pl->message ("§c * §7Unknown zone§f: §c" + zone_name); return; } // find selection auto itr = pl->selections.find (sel_name.c_str ()); if (itr == pl->selections.end ()) { pl->message ("§c * §7Unknown selection§f: §c" + sel_name); return; } world_selection *sel = itr->second; zone *zcopy = new zone (zn, sel->copy ()); w->get_zones ().remove (zn); w->get_zones ().add (zcopy); pl->message ("§eSelection changed to §b@" + sel_name + " §efor zone §3z@§b" + zn->get_name ()); }
static void _handle_pvp (player *pl, world *w, command_reader& reader) { if (!reader.has_next ()) { pl->message ("§ePvP is currently " + std::string (w->pvp ? "§aON" : "§cOFF") + " §ein world " + w->get_colored_name ()); return; } std::string arg = reader.next (); if (sutils::iequals (arg, "on")) { w->pvp = true; pl->message ("§ePvP has been turned §aON §ein world " + w->get_colored_name ()); } else if (sutils::iequals (arg, "off")) { w->pvp = false; pl->message ("§ePvP has been turned §cOFF §ein world " + w->get_colored_name ()); } else { pl->message ("§c * §7Usage§f: §e/world pvp §8on§7/§8off"); } }
static void handle_threads (player *pl, command_reader& reader) { world *wr = pl->get_world (); if (!reader.has_next ()) { std::ostringstream ss; ss << "§7This world is currently utilizing §b" << wr->physics.get_thread_count () << " §7thread" << ((wr->physics.get_thread_count () == 1) ? "" : "s"); pl->message (ss.str ()); return; } command_reader::argument narg = reader.next (); if (!narg.is_int ()) { pl->message ("§c * §7Syntax§f: §e/physics threads §c<count>"); return; } int tc = narg.as_int (); if (tc < 0 || tc > 24) { pl->message ("§c * §7Thread count must be in the range of §c0-24"); return; } wr->physics.set_thread_count (tc); pl->message ("§ePhysics thread count as been set to §a" + narg.as_str ()); }
/* * /physics - * * Changes the current state of physics of the player's world. * * Permissions: * - command.world.physics * Needed to execute the command. */ void c_physics::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.world.physics")) return; if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.no_args ()) { this->show_summary (pl); return; } std::string& opt = reader.next (); static std::unordered_map<cistring, void (*)(player *, command_reader &)> funs { { "on", handle_on }, { "off", handle_off }, { "pause", handle_pause }, { "threads", handle_threads }, }; auto itr = funs.find (opt.c_str ()); if (itr == funs.end ()) { pl->message ("§c * §7Invalid option§f: §c" + opt); return; } itr->second (pl, reader); }
/* * /unban * * Revokes a permanent ban from a specified player. * * Permissions: * - command.admin.unban * Needed to execute the command. * - command.admin.unban.ip * Required to lift IP bans. */ void c_unban::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("ip", "i"); if (!reader.parse (this, pl)) return; if (reader.no_args ()) { this->show_summary (pl); return; } std::string target_name = reader.next ().as_str (); std::string reason = reader.has_next () ? reader.all_after (0) : "No reason specified"; if (reader.opt ("ip")->found ()) { if (!pl->has ("command.admin.unban.ip")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } _unban_ip (pl, target_name); } else _unban_player (pl, target_name, reason, false); }
/* * /zone * * Zone management. * * Permissions: * - command.world.zone * Needed to execute the command. */ void c_zone::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; if (reader.no_args ()) { this->show_summary (pl); return; } std::string arg = reader.next (); static const std::unordered_map<cistring, void (*)(player *, command_reader&)> _map { { "create", _handle_create }, { "delete", _handle_delete }, { "build-perms", _handle_build_perms }, { "enter-perms", _handle_enter_perms }, { "leave-perms", _handle_leave_perms }, { "enter-msg", _handle_enter_msg }, { "leave-msg", _handle_leave_msg }, { "select", _handle_select }, { "reset", _handle_reset }, { "check", _handle_check }, }; auto itr = _map.find (arg.c_str ()); if (itr == _map.end ()) { pl->message ("§c * §7Invalid sub-command§f: §c" + arg); return; } itr->second (pl, reader); }
static void _handle_delete (player *pl, command_reader& reader) { if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/zone delete §czone-name"); return; } std::string zone_name = reader.next (); if (zone_name.size () < 3 || zone_name[0] != 'z' || zone_name[1] != '@') { pl->message ("§c * §7Invalid zone name§f: §c" + zone_name); return; } zone_name.erase (0, 2); world *w = pl->get_world (); zone *zn = w->get_zones ().find (zone_name); if (!zn) { pl->message ("§c * §7Unknown zone§f: §c" + zone_name); return; } w->get_zones ().remove (zn); pl->message ("§eZone §3z@§b" + zone_name + " §ehas been removed§f."); }
/* * /world - * * Lets the user modify or view world related information. * * Permissions: * - command.world.world * Needed to execute the command. * - command.world.world.change-members * Needed to add\remove world members. * - command.world.world.change-owners * Needed to add\remove world owners. * - command.world.world.owner.change-members * If a world owner is allowed to add\remove members. * - command.world.world.owner.change-owners * If a world owner is allowed to add\remove owners. * - command.world.world.set-perms * Required to set build-perms or join-perms * - command.world.world.get-perms * Required to view build-perms or join-perms * - commands.world.world.def-gm * Needed to change the world's default gamemode. * - commands.world.world.resize * Required to resize the world. * - commands.world.world.regenerate * Required to regenerate the world. * - commands.world.world.save * Required to save the world. * - commands.world.world.time * Required to change the time of the world. * - commands.world.world.pvp * Required to turn PvP on or off. */ void c_world::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.world.world")) return; reader.add_option ("world", "w", 1, 1); if (!reader.parse (this, pl)) return; world *w = pl->get_world (); auto opt_w = reader.opt ("world"); if (opt_w->found ()) { const std::string w_name = opt_w->arg (0).as_str (); w = pl->get_server ().get_worlds ().find (w_name.c_str ()); if (!w) { pl->message ("§c * §7Unknown world§f: §c" + w_name); return; } } if (!reader.has_next ()) _handle_no_args (pl, w); else { std::string arg1 = reader.next ().as_str (); static const std::unordered_map<cistring, void (*)(player *, world *, command_reader &)> _map { { "owners", _handle_owners }, { "members", _handle_members }, { "build-perms", _handle_build_perms }, { "join-perms", _handle_join_perms }, { "def-gm", _handle_def_gm }, { "def-inv", _handle_def_inv }, { "resize", _handle_resize }, { "regenerate", _handle_regenerate }, { "backup", _handle_backup }, { "restore", _handle_restore }, { "save", _handle_save }, { "time", _handle_time }, { "pvp", _handle_pvp }, }; auto itr = _map.find (arg1.c_str ()); if (itr == _map.end ()) { pl->message ("§c * §7Unknown sub-command§f: §c" + arg1); return; } itr->second (pl, w, reader); } }
static void _handle_def_gm (player *pl, world *w, command_reader& reader) { if (!reader.has_next ()) { if (!pl->has ("command.world.world.get-perms")) { pl->message (messages::not_allowed ()); return; } pl->message ("§6Displaying " + w->get_colored_name () + "§e'§6s default gamemode§e:"); pl->message ("§7 " + std::string ((w->def_gm == GT_CREATIVE) ? "Creative" : "Survival")); return; } const std::string arg1 = reader.next ().as_str (); if (sutils::iequals (arg1, "set")) { if (!pl->has ("command.world.world.def-gm")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/world def-gm set §cnew-def-gm"); return; } std::string val = reader.rest (); gamemode_type new_gm = GT_SURVIVAL; if (sutils::iequals (val, "survival")) ; else if (sutils::iequals (val, "creative")) new_gm = GT_CREATIVE; else { pl->message ("§c * §7Invalid gamemode§f: §c" + val); return; } pl->get_world ()->def_gm = (int)new_gm; pl->message (w->get_colored_name () + "§f'§es default gamemode has been set to§f:"); pl->message_spaced ("§f > §7" + std::string ((new_gm == GT_SURVIVAL) ? "Survival" : "Creative")); } else { pl->message ("§c * §7Invalid sub-command§f: §cdef-gm." + arg1); return; } }
static void _handle_restore (player *pl, world *w, command_reader& reader) { if (!pl->has ("command.world.world.restore")) { pl->message (messages::not_allowed ()); return; } if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/world restore §cbackup-number"); return; } int backup_num; auto arg = reader.next (); if (!arg.is_int () || ((backup_num = arg.as_int ()) <= 0)) { pl->message ("§c * §7The backup number should a positive non-zero integer§c."); return; } std::string src = w->get_path (); src.erase (0, 12); // remove "data/worlds/" part src.insert (0, "data/backups/" + std::string (w->get_name ()) + "/"); std::ostringstream ss; ss << src << "." << backup_num; FILE *f = std::fopen (ss.str ().c_str (), "rb"); if (!f) { pl->message ("§c * §7Backup does not exist§c."); return; } std::fclose (f); _copy_file (w->get_path (), ss.str ().c_str ()); w->reload_world (w->get_name ()); w->get_players ().all ( [] (player *pl) { std::cout << "W a" << std::endl; pl->rejoin_world (); std::cout << "W b" << std::endl; pl->message ("§bWorld reloaded"); }); ss.str (std::string ()); ss << "§eRestored backup #§b" << backup_num; pl->message (ss.str ()); }
static void _handle_select (player *pl, command_reader& reader) { if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/zone select §czone-name"); return; } std::string zone_name = reader.next (); if (zone_name.size () < 3 || zone_name[0] != 'z' || zone_name[1] != '@') { pl->message ("§c * §7Invalid zone name§f: §c" + zone_name); return; } zone_name.erase (0, 2); world *w = pl->get_world (); zone *zn = w->get_zones ().find (zone_name); if (!zn) { pl->message ("§c * §7Unknown zone§f: §c" + zone_name); return; } std::ostringstream ss; ss << pl->sb_next_unused (); std::string sel_name = ss.str (); world_selection *sel = zn->get_selection ()->copy (); pl->selections[sel_name.c_str ()] = sel; pl->curr_sel = sel; sel->show (pl); pl->sb_commit (); pl->message ("§eCreated new selection §b@" + sel_name + " §efrom zone §3z@§b" + zn->get_name ()); }
static void _handle_create (player *pl, command_reader& reader) { if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/zone create §czone-name"); return; } std::string zone_name = reader.next (); if (zone_name.size () < 3 || zone_name[0] != 'z' || zone_name[1] != '@') { pl->message ("§c * §7Invalid zone name§f: §c" + zone_name); return; } zone_name.erase (0, 2); // TODO: Group all active selections into one compound selection, // and turn that into a zone. if (!pl->curr_sel) { pl->message ("§c * §7You must have an active selection§c."); return; } world *w = pl->get_world (); if (w->get_zones ().find (zone_name)) { pl->message ("§c * §7A zone with that name already exists§c."); return; } zone *zn = new zone (zone_name, pl->curr_sel->copy ()); w->get_zones ().add (zn); pl->message ("§eCreated new zone§f: §3z@§b" + zone_name); }
/* /kick * * Kicks a player from the server. * * Permissions: * - command.admin.kick * Needed to execute the command. */ void c_kick::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("message", "m", 1, 1); if (!reader.parse (this, pl)) return; if (reader.no_args ()) { this->show_summary (pl); return; } std::string& target_name = reader.next ().as_str (); std::string reason = reader.has_next () ? reader.all_after (0) : "No reason specified"; std::string kick_msg = "§c"; { auto opt = reader.opt ("message"); if (opt->found ()) kick_msg.append (opt->arg (0).as_str ()); else kick_msg.append ("You have been kicked from the server"); } player *target = pl->get_server ().get_players ().find (target_name.c_str ()); if (!target) { pl->message ("§c * §7No such player§f: §c" + target_name); return; } else if (target->bad ()) return; server& srv = pl->get_server (); // record kick { auto& conn = pl->get_server ().sql ().pop (); try { sqlops::record_kick (conn, target->get_username (), pl->get_username (), reason.c_str ()); } catch (const std::exception& ex) { pl->message ("§4 * §cAn error has occurred while recording kick message"); } pl->get_server ().sql ().push (conn); std::ostringstream ss; ss << "§7 | §eRecorded kick message§7: §c\"" << reason << "§c\""; pl->message (ss.str ()); } { std::ostringstream ss; ss << "§4 > " << target->get_colored_nickname () << " §chas been kicked by " << pl->get_colored_nickname () << "§c!"; srv.get_players ().message (ss.str ()); } target->kick (kick_msg.c_str (), reason.c_str ()); }
/* * /gm - * * Changes the gamemode of the executor or of a specified player. * * Permissions: * - command.admin.gm * Needed to execute the command. */ void c_gm::execute (player *pl, command_reader& reader) { if (!pl->perm ("command.admin.gm")) return; if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 2) { this->show_summary (pl); return; } player *target = pl; if (reader.arg_count () == 2) { std::string& plname = reader.next ().as_str (); target = pl->get_server ().get_players ().find (plname.c_str ()); if (!target) { pl->message ("§c * §7No such player§f: §c" + plname); return; } } std::string& gmstr = reader.next ().as_str (); gamemode_type gm = GT_SURVIVAL; if (gmstr.size () == 1) { switch (gmstr[0]) { case 's': break; case 'c': gm = GT_CREATIVE; break; //case 'a': gm = GT_ADVENTURE; break; default: pl->message ("§c * §7Invalid gamemode type§f: §c" + gmstr); return; } } else { if (sutils::iequals (gmstr, "survival")) ; else if (sutils::iequals (gmstr, "creative")) gm = GT_CREATIVE; //else if (sutils::iequals (gmstr, "adventure")) // gm = GT_ADVENTURE; else { pl->message ("§c * §7Invalid gamemode type§f: §c" + gmstr); return; } } if (gm == target->gamemode ()) { if (pl == target) target->message ("§c * §7You already have that gamemode set§f."); else { std::ostringstream ss; ss << "§c * §7" << target->get_colored_username () << " §7already has that gamemode set§f."; target->message (ss.str ()); } return; } const char *gm_name = (gm == GT_SURVIVAL) ? "survival" : ((gm == GT_CREATIVE) ? "creative" : "adventure"); if (pl != target) { std::ostringstream ss; ss << target->get_colored_username () << " §egamemode has been set to§f: §4" << gm_name; pl->message (ss.str ()); } target->change_gamemode (gm); /* // Commented out due to Minecraft's ugly "Your gamemode has been updated." // message. std::ostringstream ss; ss << "§6Your gamemode has been set to§f: §c" << gm_name; target->message (ss.str ()); */ }
static void _handle_build_perms (player *pl, command_reader& reader) { if (!reader.has_next ()) { pl->message ("§c * §7Usage§f:"); pl->message ("§c * (1) §e/zone build-perms §czone-name"); pl->message ("§c * (2) §e/zone build-perms §czone-name §eset §cperms"); pl->message ("§c * (3) §e/zone build-perms §czone-name §eclear"); return; } std::string zone_name = reader.next (); if (zone_name.size () < 3 || zone_name[0] != 'z' || zone_name[1] != '@') { pl->message ("§c * §7Invalid zone name§f: §c" + zone_name); return; } zone_name.erase (0, 2); zone *zn = pl->get_world ()->get_zones ().find (zone_name); if (!zn) { pl->message ("§c * §7Unknown zone§f: §cz@" + zone_name); return; } zone_name = zn->get_name (); if (!reader.has_next ()) { pl->message ("§9Displaying build perms for zone §3z@§b" + zone_name); if (zn->get_security ().get_build_perms ().empty ()) pl->message ("§8 not set"); else pl->message ("§7 " + zn->get_security ().get_build_perms ()); return; } else { std::string arg = reader.next (); if (sutils::iequals (arg, "set")) { if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/zone build-perms §czone-name §eset §cperms"); return; } std::string perms = reader.rest (); zn->get_security ().set_build_perms (perms); pl->message ("§eZone §3z@§b" + zone_name + "§e's build perms have been set to§f:"); pl->message ("§f > §7" + perms); } else if (sutils::iequals (arg, "clear")) { zn->get_security ().set_build_perms (""); pl->message ("§eZone §3z@§b" + zone_name + "§e's build perms have been cleared"); } else { pl->message ("§c * Invalid sub-command§f: §cbuild-perms." + arg); } } }
/* * /sphere - * * Draws a three-dimensional sphere centered at a point. * * Permissions: * - command.draw.sphere * Needed to execute the command. */ void c_sphere::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("fill", "f"); if (!reader.parse (this, pl)) return; if (reader.no_args () || reader.arg_count () > 3) { this->show_summary (pl); return; } bool do_fill = reader.opt ("fill")->found (); std::string& str = reader.next ().as_str (); if (!sutils::is_block (str)) { pl->message ("§c * §7Invalid block§f: §c" + str); return; } blocki bl = sutils::to_block (str); if (bl.id == BT_UNKNOWN) { pl->message ("§c * §7Unknown block§f: §c" + str); return; } int radius = -1; if (reader.has_next ()) { command_reader::argument arg = reader.next (); if (!arg.is_int ()) { pl->message ("§c * §7Usage§f: §e/sphere §cblock §8[§cradius§8]"); return; } radius = arg.as_int (); if (radius <= 0) { pl->message ("§c * §7Radius must be greater than zero.§f"); return; } } sphere_data *data = new sphere_data {bl, radius, do_fill}; pl->create_data ("sphere", data, [] (void *ptr) { delete static_cast<sphere_data *> (ptr); }); pl->get_nth_marking_callback ((radius == -1) ? 2 : 1) += on_blocks_marked; std::ostringstream ss; ss << "§8Sphere §7("; if (radius != -1) ss << "§8Radius§7: §b" << radius << "§7, "; ss << "§8Block§7: §b" << str << "§7):"; pl->message (ss.str ()); ss.str (std::string ()); ss.clear (); ss << "§8 * §7Please mark §b" << ((radius == -1) ? 2 : 1) << " §7block" << ((radius == -1) ? "s" : "") << "§7."; pl->message (ss.str ()); }
static void _handle_time (player *pl, world *w, command_reader& reader) { std::ostringstream ss; if (!reader.has_next ()) { pl->message ("§6Displaying world time for " + w->get_colored_name () + "§e:"); pl->message ("§7 " + _get_time_str (w->get_time ()) + (w->is_time_frozen () ? " [Frozen]" : "")); return; } std::string arg = reader.next (); if (sutils::iequals (arg, "set")) { if (!pl->has ("command.world.world.time")) { pl->message (messages::not_allowed ()); return; } if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/world time set §ctime"); return; } unsigned long long time = 0; arg = reader.next ().as_str (); if (!_parse_time (arg, time)) { pl->message ("§c * §7Invalid time string§c."); return; } w->set_time (time); ss << "§eWorld time for " << w->get_colored_name () << " §ehas been set to§f: §9" << _get_time_str (time) << " §f[§9" << (time % 24000) << " ticks§f]"; pl->message (ss.str ()); } else if (sutils::iequals (arg, "stop")) { if (!pl->has ("command.world.world.time")) { pl->message (messages::not_allowed ()); return; } if (w->is_time_frozen ()) { pl->message ("§c * §Time is already frozen in this world§c."); return; } w->stop_time (); pl->message ("§eWorld time has been stopped in world " + w->get_colored_name ()); } else if (sutils::iequals (arg, "resume")) { if (!pl->has ("command.world.world.time")) { pl->message (messages::not_allowed ()); return; } if (!w->is_time_frozen ()) { pl->message ("§c * §Time is not frozen in this world§c."); return; } w->resume_time (); pl->message ("§eWorld time has been resumed in world " + w->get_colored_name ()); } else { pl->message ("§c * §7Unknown sub-command§f: §ctime." + arg); } }
/* /rank * * Changes the rank of a specified player. * * Permissions: * - command.admin.rank * Needed to execute the command. */ void c_rank::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; reader.add_option ("quiet", "q"); if (!reader.parse (this, pl)) return; if (reader.arg_count () != 2) { this->show_summary (pl); return; } bool quiet = reader.opt ("quiet")->found (); enum { ACT_RANK, ACT_PROMOTE, ACT_DEMOTE, } action = ACT_RANK; std::string target_name; rank new_rank; std::string arg1 = reader.next (); if (sutils::iequals (arg1, "promote")) { action = ACT_PROMOTE; target_name = reader.next ().as_str (); } else if (sutils::iequals (arg1, "demote")) { action = ACT_DEMOTE; target_name = reader.next ().as_str (); } else { target_name = arg1; std::string rank_str = reader.next (); if (sutils::iequals (rank_str, "up")) action = ACT_PROMOTE; else if (sutils::iequals (rank_str, "down")) action = ACT_DEMOTE; else { try { new_rank.set (rank_str.c_str (), pl->get_server ().get_groups ()); } catch (const std::exception& str) { pl->message ("§c * §7Invalid rank§f: §c" + rank_str); return; } } } player *target = nullptr; sqlops::player_info pinf; { soci::session sql (pl->get_server ().sql_pool ()); if (!sqlops::player_data (sql, target_name.c_str (), pl->get_server (), pinf)) { pl->message ("§c * §7Unknown player§f: §c" + target_name); return; } target_name.assign (pinf.name); target = pl->get_server ().get_players ().find (target_name.c_str ()); if (action == ACT_PROMOTE || action == ACT_DEMOTE) { if (!get_next_rank (pl, pinf.rnk, new_rank, action == ACT_PROMOTE)) return; } if (!pl->is_op ()) { if (target_name == pl->get_username ()) { pl->message ("§c * §7You cannot change your own rank§c."); return; } else if (pinf.rnk >= pl->get_rank ()) { pl->message ("§c * §7You cannot change the rank of someone higher than you§c."); return; } else if (new_rank >= pl->get_rank ()) { pl->message ("§c * §7You cannot give a player a rank that is higher than yours§c."); return; } } try { std::string rank_str; new_rank.get_string (rank_str); sqlops::modify_player_rank (sql, target_name.c_str (), rank_str.c_str ()); } catch (const std::exception& ex) { pl->message ("§c * §4Failed to update database§c."); } // update the player's in-game status. if (target) { target->set_rank (new_rank); if (!quiet) { group *main = new_rank.main (); std::ostringstream ss; ss << "§9 > §" << pinf.rnk.main ()->color << pinf.nick << "§7's rank has been set to" //<< (is_vowel (main->name[0]) ? "n" : "") << " §" << main->color << main->name << "§7!"; pl->get_server ().get_players ().message (ss.str ()); } } { std::ostringstream ss; ss << "§7 | The database has been updated."; pl->message (ss.str ()); } } }
static void _pay_give_take (player *pl, command_reader& reader, _m_action act) { if ( ((act == M_PAY) && !pl->has ("command.info.money.pay")) || ((act == M_TAKE || act == M_GIVE) && !pl->has ("command.info.money.give")) ) { pl->message ("§c * §7You are not allowed to do that§c."); return; } else if (reader.arg_count () != 3) { if (act == M_PAY) pl->message ("§c * §7Usage§c: §e/money pay §cplayer amount"); else if (act == M_GIVE) pl->message ("§c * §7Usage§c: §e/money give §cplayer amount"); else pl->message ("§c * §7Usage§c: §e/money take §cplayer amount"); return; } std::string target_name = reader.next (); double amount = reader.next ().as_float (); if (act == M_PAY) { if (sutils::iequals (target_name, pl->get_username ())) { pl->message ("§c * §7You cannot send yourself money§c."); return; } if (amount < 0.01) { pl->message ("§c * §7Invalid amount§c."); return; } else if (amount > pl->bal) { double left = amount - pl->bal; if (left < 10000000.0) pl->message ("§c * §7You are §c$" + utils::format_number (left, 2) + " §7short§c."); else pl->message ("§c * §7Not enough money§c."); return; } } else if (act == M_TAKE) { amount = -amount; if (amount >= 0.0) { pl->message ("§c * §7Invalid amount§c."); return; } } else if (amount <= 0.0) { pl->message ("§c * §7Invalid amount§c."); return; } std::string colored_target_name; // the easy way player *target = pl->get_server ().get_players ().find (target_name.c_str ()); if (target) { if (act == M_PAY) pl->bal -= amount; target->bal += amount; target_name.assign (target->get_username ()); colored_target_name.assign (target->get_colored_username ()); } else { // the hard way soci::session sql (pl->get_server ().sql_pool ()); try { if (!sqlops::player_exists (sql, target_name.c_str ())) { pl->message ("§c * §7No such player§f: §c" + target_name); return; } if (act == M_PAY) pl->bal -= amount; sqlops::add_money (sql, target_name.c_str (), amount); colored_target_name.assign (sqlops::player_colored_name (sql, target_name.c_str (), pl->get_server ())); target_name.assign (sqlops::player_name (sql, target_name.c_str ())); } catch (const std::exception& ex) { pl->message ("§4 * §cAn error has occurred§4."); return; } } std::ostringstream ss; if (act == M_PAY) ss << "§7$" << utils::format_number (amount, 2) << " §ehas been sent to " << colored_target_name; else if (act == M_GIVE) ss << "§7$" << utils::format_number (amount, 2) << " §ehas been added to " << colored_target_name << "§e's account"; else ss << "§7$" << utils::format_number (-amount, 2) << " §ehas been taken from " << colored_target_name << "§e's account"; pl->message (ss.str ()); if ((act != M_TAKE) && (target && target != pl)) { ss.clear (); ss.str (std::string ()); ss << pl->get_colored_username () << " §ehas sent you §7$" << utils::format_number (amount, 2); target->message (ss.str ()); } if (act == M_TAKE) amount = -amount; pl->get_logger () (LT_SYSTEM) << pl->get_username () << " has " << ((act == M_PAY) ? "sent" : ((act == M_GIVE) ? "given" : "taken")) << " $" << utils::format_number (amount, 2) << ((act == M_TAKE) ? " from " : " to ") << target_name << std::endl; return; }
/* * /money - * * Displays the amount of money a player has. * * Permissions: * - command.info.money * Needed to execute the command. * - command.info.money.others * Required to display the amount of money _other_ players have. * - command.info.money.pay * Whether the player is allowed to send money out of their own account. * - command.info.money.give * Whether the player is allowed to give money to players _wihout_ * taking it out of their own account. * - command.info.money.set * Required to modify a player's balance directly. */ void c_money::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; bool someone_else = false; std::string target_name; if (!reader.has_next ()) { target_name.assign (pl->get_username ()); } else { std::string& a = reader.next (); if (sutils::iequals (a, "pay")) { do_pay (pl, reader); return; } else if (sutils::iequals (a, "give")) { do_give (pl, reader); return; } else if (sutils::iequals (a, "take")) { do_take (pl, reader); return; } else if (sutils::iequals (a, "set")) { do_set (pl, reader); return; } else { target_name = a; someone_else = true; } } // // /money [player] // std::ostringstream ss; if (someone_else) { if (!pl->has ("command.info.money.others")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } if (sutils::iequals (target_name, pl->get_username ())) ss << "§2Balance§8: §a$§f" << utils::format_number (pl->bal, 2); else { player *target = pl->get_server ().get_players ().find (target_name.c_str ()); if (target) ss << target->get_colored_username () << "§e's balance§f: §a$§f" << utils::format_number (target->bal, 2); else { soci::session sql (pl->get_server ().sql_pool ()); try { if (!sqlops::player_exists (sql, target_name.c_str ())) { pl->message ("§c * §7No such player§f: §c" + target_name); return; } ss << sqlops::player_colored_name (sql, target_name.c_str (), pl->get_server ()) << "§2's balance§f: §a$§f" << utils::format_number (sqlops::get_money (sql, target_name.c_str ()), 2); } catch (const std::exception& ex) { pl->message ("§4 * §cAn error has occurred§4."); return; } } } } else ss << "§2Balance§f: §a$§f" << utils::format_number (pl->bal, 2); pl->message (ss.str ()); }
static void _handle_resize (player *pl, world *w, command_reader& reader) { if (!pl->has ("command.world.world.resize")) { pl->message (messages::not_allowed ()); return; } if (reader.arg_count () != 3) { pl->message ("§c * §7Usage§f: §e/world resize §cwidth depth"); return; } int width = 0, depth = 0; auto a_width = reader.next (); auto a_depth = reader.next (); if (!a_width.is_int ()) { if (sutils::iequals (a_width.as_str (), "inf")) width = 0; else { pl->message ("§c * §7Both width and depth must be non-zero positive integers§c."); return; } } else { width = a_width.as_int (); if (width <= 0) { pl->message ("§c * §7Both width and depth must be non-zero positive integers§c."); return; } } if (!a_depth.is_int ()) { if (sutils::iequals (a_depth.as_str (), "inf")) depth = 0; else { pl->message ("§c * §7Both width and depth must be non-zero positive integers§c."); return; } } else { depth = a_depth.as_int (); if (depth <= 0) { pl->message ("§c * §7Both width and depth must be non-zero positive integers§c."); return; } } if (width == w->get_width () && depth == w->get_depth ()) { pl->message ("§c * §7The world is already in that size§c."); return; } w->set_size (width, depth); w->get_players ().all ( [] (player *pl) { pl->rejoin_world (false); pl->message ("§bWorld reloaded"); }); }
static void _handle_def_inv (player *pl, world *w, command_reader& reader) { if (!reader.has_next ()) { if (!pl->has ("command.world.world.get-perms")) { pl->message (messages::not_allowed ()); return; } pl->message ("§6Displaying " + w->get_colored_name () + "§e'§6s default inventory§e:"); if (!w->use_def_inv) pl->message ("§7 Default inventory disabled"); else pl->message ("§7 " + w->def_inv); return; } std::string arg = reader.next (); if (sutils::iequals (arg, "set")) { if (!pl->has ("command.world.world.def-inv")) { pl->message (messages::not_allowed ()); return; } if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/world def-inv set §cdef-inv..."); return; } w->def_inv = reader.rest (); pl->message (w->get_colored_name () + "§f's §edefault inventory has been set to§f:"); pl->message ("§7 | " + w->def_inv); } else if (sutils::iequals (arg, "clear")) { if (!pl->has ("command.world.world.def-inv")) { pl->message (messages::not_allowed ()); return; } w->def_inv = ""; pl->message (w->get_colored_name () + "§f's §edefault inventory has been cleared§f."); } else if (sutils::iequals (arg, "disable")) { if (!pl->has ("command.world.world.def-inv")) { pl->message (messages::not_allowed ()); return; } if (!w->use_def_inv) { pl->message ("§c * §7Default inventories are already disabled in this world§c."); return; } w->def_inv = ""; w->use_def_inv = false; pl->message ("§eDefault inventories in " + w->get_colored_name () + " §ehave been disabled§f."); } else if (sutils::iequals (arg, "enable")) { if (!pl->has ("command.world.world.def-inv")) { pl->message (messages::not_allowed ()); return; } if (w->use_def_inv) { pl->message ("§c * §7Default inventories are already enabled in this world§c."); return; } w->use_def_inv = true; pl->message ("§eDefault inventories in " + w->get_colored_name () + " §ehave been enabled§f."); } else { pl->message ("§c * §7Invalid sub-command§f: §cdef-inv." + arg); } }
/* * /portal - * * Turns blocks in the user's selected area to portals. * * Permissions: * - command.world.portal * Needed to execute the command. * - command.world.portal.interworld * Needed to place portals between different worlds. */ void c_portal::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; if (reader.no_args ()) { pl->message ("§c * §7Usage§f: §e/portal §ctarget-block §8[§creplace-block§8]"); return; } std::string& target_block_str = reader.next ().as_str (); if (sutils::iequals (target_block_str, "exit")) { _finish_portal (pl); return; } else if (sutils::iequals (target_block_str, "cancel")) { _cancel_portal (pl); return; } else { portal_data *data = static_cast<portal_data *> (pl->get_data ("portal")); if (data) { pl->message ("§c * §7Type §c/portal cancel §7to cancel your previous portal§c."); return; } } if (pl->selections.empty ()) { pl->message ("§c * §7You§f'§7re not selecting anything§f."); return; } world_selection *sel = pl->curr_sel; world *w = pl->get_world (); blocki target_block; if (!(target_block = sutils::to_block (target_block_str)).valid ()) { pl->message ("§c * §7Invalid block§f: §c" + target_block_str); return; } blocki replace_block = target_block; if (reader.has_next ()) { std::string& replace_block_str = reader.next ().as_str (); if (!(replace_block = sutils::to_block (replace_block_str)).valid ()) { pl->message ("§c * §7Invalid block§f: §c" + replace_block_str); return; } } if (!pl->get_world ()->security ().can_build (pl)) { pl->message ("§4 * §cYou are not allowed to build here§4."); return; } int blocks = 0; sparse_edit_stage *es = new sparse_edit_stage (pl->get_world ()); portal *ptl = new portal (); block_pos smin = sel->min (), smax = sel->max (); if (smin.y < 0) smin.y = 0; if (smin.y > 255) smin.y = 255; if (smax.y < 0) smax.y = 0; if (smax.y > 255) smax.y = 255; for (int x = smin.x; x <= smax.x; ++x) for (int y = smin.y; y <= smax.y; ++y) for (int z = smin.z; z <= smax.z; ++z) { if (!w->in_bounds (x, y, z)) continue; if (sel->contains (x, y, z)) { block_data bd = w->get_block (x, y, z); if (bd.id == target_block.id && bd.meta == target_block.meta) { es->set (x, y, z, replace_block.id, replace_block.meta, BE_PORTAL); ptl->affected.emplace_back (x, y, z); ++ blocks; } } } ptl->calc_bounds (); portal_data *data = new portal_data {w, es, ptl}; pl->create_data ("portal", data, [] (void *ptr) { delete static_cast<portal_data *> (ptr); }); { std::ostringstream ss; ss << "§7 | §b" << blocks << " §eentrance blocks have been marked."; pl->message (ss.str ()); pl->message ("§7 | §eType §c/portal exit §eto complete the portal."); pl->message ("§7 | §eIf you wish to cancel the portal, type §c/portal cancel"); } }
static void _handle_join_perms (player *pl, world *w, command_reader& reader) { if (!reader.has_next ()) { if (!pl->has ("command.world.world.get-perms")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } std::ostringstream ss; ss << "§6Displaying " << w->get_colored_name () << "§e'§6s join permissions§e:"; pl->message (ss.str ()); ss.str (std::string ()); const std::string& perms = w->security ().get_join_perms (); if (perms.empty ()) ss << "§8 not set"; else ss << "§7 " << perms; pl->message (ss.str ()); return; } const std::string arg1 = reader.next ().as_str (); if (sutils::iequals (arg1, "set")) { if (!pl->has ("command.world.world.set-perms")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/world join-perms set §cnew-join-perms"); return; } std::string val = reader.rest (); w->security ().set_join_perms (val); pl->message (w->get_colored_name () + "§f'§es join-perms has been set to§f:"); pl->message_spaced ("§f > §7" + val); } else if (sutils::iequals (arg1, "clear")) { if (!pl->has ("command.world.world.set-perms")) { pl->message ("§c * §7You are not allowed to do that§c."); return; } w->security ().set_join_perms (""); pl->message (w->get_colored_name () + "§f'§es join-perms has been cleared"); } else { pl->message ("§c * §7Invalid sub-command§f: §cjoin-perms." + arg1); return; } }
static void _handle_leave_msg (player *pl, command_reader& reader) { if (!reader.has_next ()) { pl->message ("§c * §7Usage§f:"); pl->message ("§c * (1) §e/zone leave-msg §czone-name"); pl->message ("§c * (2) §e/zone leave-msg §czone-name §eset §cmsg"); pl->message ("§c * (3) §e/zone leave-msg §czone-name §eclear"); return; } std::string zone_name = reader.next (); if (zone_name.size () < 3 || zone_name[0] != 'z' || zone_name[1] != '@') { pl->message ("§c * §7Invalid zone name§f: §c" + zone_name); return; } zone_name.erase (0, 2); zone *zn = pl->get_world ()->get_zones ().find (zone_name); if (!zn) { pl->message ("§c * §7Unknown zone§f: §cz@" + zone_name); return; } zone_name = zn->get_name (); if (!reader.has_next ()) { pl->message ("§9Displaying the leave message for zone §3z@§b" + zone_name); if (zn->get_leave_msg ().empty ()) pl->message ("§8 not set"); else pl->message ("§7 " + zn->get_leave_msg ()); return; } else { std::string arg = reader.next (); if (sutils::iequals (arg, "set")) { if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/zone leave-msg §czone-name §eset §cmsg"); return; } std::string msg = "§b" + reader.rest (); zn->set_leave_msg (msg); pl->message ("§eZone §3z@§b" + zone_name + "§e's leave message has been set to§f:"); pl->message ("§f > §7" + msg); } else if (sutils::iequals (arg, "clear")) { zn->set_leave_msg (""); pl->message ("§eZone §3z@§b" + zone_name + "§e's leave message has been cleared"); } else { pl->message ("§c * Invalid sub-command§f: §cleave-msg." + arg); } } }
/* /unban * * Revokes a permanent ban from a specified player. * * Permissions: * - command.admin.unban * Needed to execute the command. */ void c_unban::execute (player *pl, command_reader& reader) { if (!pl->perm (this->get_exec_permission ())) return; if (!reader.parse (this, pl)) return; if (reader.no_args ()) { this->show_summary (pl); return; } std::string target_name = reader.next ().as_str (); std::string reason = reader.has_next () ? reader.all_after (0) : "No reason specified"; player *target = pl->get_server ().get_players ().find (target_name.c_str ()); if (target) { if (target == pl) { pl->message ("§c * §7You are not banned§c."); return; } pl->message ("§c * §7That player is online§c..."); return; } std::string target_colored_nick; server& srv = pl->get_server (); // record unban { auto& conn = pl->get_server ().sql ().pop (); try { if (!sqlops::player_exists (conn, target_name.c_str ())) { pl->message ("§c * §7No such player§f: §c" + target_name); pl->get_server ().sql ().push (conn); return; } if (!sqlops::is_banned (conn, target_name.c_str ())) { pl->message ("§c * §7Player is not banned§c."); pl->get_server ().sql ().push (conn); return; } target_name = sqlops::player_name (conn, target_name.c_str ()); target_colored_nick = sqlops::player_colored_nick (conn, target_name.c_str (), pl->get_server ()); sqlops::modify_ban_status (conn, target_name.c_str (), false); sqlops::record_unban (conn, target_name.c_str (), pl->get_username (), reason.c_str ()); } catch (const std::exception& ex) { pl->message ("§4 * §cAn error has occurred while recording unban message"); } pl->get_server ().sql ().push (conn); std::ostringstream ss; ss << "§7 | §eRecorded unban message§7: §c\"" << reason << "§c\""; pl->message (ss.str ()); } { std::ostringstream ss; ss << "§8 > " << target_colored_nick << " §8has been unbanned by " << pl->get_colored_nickname () << "§8!"; srv.get_players ().message (ss.str ()); } }
static void _handle_members (player *pl, world *w, command_reader& reader) { world_security& sec = w->security (); if (!reader.has_next ()) { std::ostringstream ss; ss << "§6Displaying members for " << w->get_colored_name () << "§e:"; pl->message (ss.str ()); ss.str (std::string ()); const auto& member_pids = sec.get_members (); if (member_pids.empty ()) pl->message ("§8 none"); else _print_names_from_pids (pl, member_pids); return; } const std::string arg1 = reader.next ().as_str (); if (sutils::iequals (arg1, "add")) { if (!pl->has ("command.world.world.change-members") && !(sec.is_owner (pl->pid ()) && pl->has ("command.world.world.owner.change-members"))) { pl->message ("§c * §7You are not allowed to do that§c."); return; } if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/world members add §cplayer"); return; } const std::string arg2 = reader.next ().as_str (); // fetch player info soci::session sql {pl->get_server ().sql_pool ()}; sqlops::player_info pinf; if (!sqlops::player_data (sql, arg2.c_str (), pl->get_server (), pinf)) { pl->message ("§c * §7Unknown player§f: §c" + arg2); return; } if (sec.is_member (pinf.id)) { std::ostringstream ss; ss << "§c * §" << pinf.rnk.main ()->color << pinf.name << " §7is already a member of this world§c."; pl->message (ss.str ()); return; } sec.add_member (pinf.id); std::ostringstream ss; ss << "§" << pinf.rnk.main ()->color << pinf.name << " §ehas been added to the world§f'§es member list§f."; pl->message (ss.str ()); } else if (sutils::iequals (arg1, "remove") || sutils::iequals (arg1, "del")) { if (!pl->has ("command.world.world.change-members") && !(sec.is_owner (pl->pid ()) && pl->has ("command.world.world.owner.change-members"))) { pl->message ("§c * §7You are not allowed to do that§c."); return; } if (!reader.has_next ()) { pl->message ("§c * §7Usage§f: §e/world members remove §cplayer"); return; } const std::string arg2 = reader.next ().as_str (); // fetch player info soci::session sql {pl->get_server ().sql_pool ()}; sqlops::player_info pinf; if (!sqlops::player_data (sql, arg2.c_str (), pl->get_server (), pinf)) { pl->message ("§c * §7Unknown player§f: §c" + arg2); return; } if (!sec.is_member (pinf.id)) { std::ostringstream ss; ss << "§c * §" << pinf.rnk.main ()->color << pinf.name << " §7is not a member of this world§c."; pl->message (ss.str ()); return; } sec.remove_member (pinf.id); std::ostringstream ss; ss << "§" << pinf.rnk.main ()->color << pinf.name << " §ehas been removed from the world§f'§es member list§f."; pl->message (ss.str ()); } else { pl->message ("§c * §7Unknown sub-command§f: §cmembers." + arg1); return; } }