mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-18 03:39:04 -04:00
More work on games rewrite
This commit is contained in:
parent
773e9f8152
commit
91b8bf44ac
@ -35,8 +35,8 @@ namespace MCGalaxy.Gui {
|
||||
|
||||
void UpdateLavaControls() {
|
||||
try {
|
||||
ls_btnStartGame.Enabled = !Server.lava.active;
|
||||
ls_btnStopGame.Enabled = Server.lava.active;
|
||||
ls_btnStartGame.Enabled = !Server.lava.running;
|
||||
ls_btnStopGame.Enabled = Server.lava.running;
|
||||
ls_btnEndRound.Enabled = Server.lava.roundActive;
|
||||
lsBtnEndVote.Enabled = Server.lava.voteActive;
|
||||
}
|
||||
@ -44,12 +44,12 @@ namespace MCGalaxy.Gui {
|
||||
}
|
||||
|
||||
void lsBtnStartGame_Click(object sender, EventArgs e) {
|
||||
if (!Server.lava.active) Server.lava.Start();
|
||||
if (!Server.lava.running) Server.lava.Start();
|
||||
UpdateLavaControls();
|
||||
}
|
||||
|
||||
void lsBtnStopGame_Click(object sender, EventArgs e) {
|
||||
if (Server.lava.active) Server.lava.Stop();
|
||||
if (Server.lava.running) Server.lava.Stop();
|
||||
UpdateLavaControls();
|
||||
}
|
||||
|
||||
@ -109,9 +109,9 @@ namespace MCGalaxy.Gui {
|
||||
|
||||
Server.lava.AddMap(name);
|
||||
|
||||
LavaSurvival.MapSettings settings = Server.lava.LoadMapSettings(level.name);
|
||||
settings.blockFlood = new Vec3U16((ushort)(level.Width / 2), (ushort)(level.Height - 1), (ushort)(level.Length / 2));
|
||||
settings.blockLayer = new Vec3U16(0, (ushort)(level.Height / 2), 0);
|
||||
LSGame.MapSettings settings = Server.lava.LoadMapSettings(level.name);
|
||||
settings.FloodPos = new Vec3U16((ushort)(level.Width / 2), (ushort)(level.Height - 1), (ushort)(level.Length / 2));
|
||||
settings.LayerPos = new Vec3U16(0, (ushort)(level.Height / 2), 0);
|
||||
ushort x = (ushort)(level.Width / 2), y = (ushort)(level.Height / 2), z = (ushort)(level.Length / 2);
|
||||
settings.safeZone = new Vec3U16[] { new Vec3U16((ushort)(x - 3), y, (ushort)(z - 3)), new Vec3U16((ushort)(x + 3), (ushort)(y + 4), (ushort)(z + 3)) };
|
||||
Server.lava.SaveMapSettings(settings);
|
||||
@ -167,7 +167,7 @@ namespace MCGalaxy.Gui {
|
||||
ls_grpMapSettings.Text = "Map settings (" + name + ")";
|
||||
|
||||
try {
|
||||
LavaSurvival.MapSettings m = Server.lava.LoadMapSettings(name);
|
||||
LSGame.MapSettings m = Server.lava.LoadMapSettings(name);
|
||||
pg_lavaMap.SelectedObject = new LavaMapProperties(m);
|
||||
} catch (Exception ex) {
|
||||
Logger.LogError(ex);
|
||||
|
@ -1,66 +1,66 @@
|
||||
/*
|
||||
Copyright 2015 MCGalaxy
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MCGalaxy.Games;
|
||||
|
||||
namespace MCGalaxy.Gui {
|
||||
public sealed class LavaMapProperties {
|
||||
internal readonly LavaSurvival.MapSettings m;
|
||||
|
||||
public LavaMapProperties(LavaSurvival.MapSettings m) {
|
||||
this.m = m;
|
||||
}
|
||||
|
||||
[DisplayName("Fast lava chance")]
|
||||
public byte FastLava { get { return m.fast; } set { m.fast = Clamp(value); } }
|
||||
|
||||
[DisplayName("Killer liquids chance")]
|
||||
public byte Killer { get { return m.killer; } set { m.killer = Clamp(value); } }
|
||||
|
||||
[DisplayName("Destroy blocks chance")]
|
||||
public byte Destroy { get { return m.destroy; } set { m.destroy = Clamp(value); } }
|
||||
|
||||
[DisplayName("Water flood chance")]
|
||||
public byte Water { get { return m.water; } set { m.water = Clamp(value); } }
|
||||
|
||||
[DisplayName("Layer flood chance")]
|
||||
public byte Layer { get { return m.layer; } set { m.layer = Clamp(value); } }
|
||||
|
||||
|
||||
[DisplayName("Layer height")]
|
||||
public int LayerHeight { get { return m.layerHeight; } set { m.layerHeight = ClampI(value); } }
|
||||
|
||||
[DisplayName("Layer count")]
|
||||
public int LayerCount { get { return m.layerCount; } set { m.layerCount = ClampI(value); } }
|
||||
|
||||
[DisplayName("Layer time (mins)")]
|
||||
public double LayerTime { get { return m.layerInterval; } set { m.layerInterval = ClampD(value); } }
|
||||
|
||||
[DisplayName("Round time (mins)")]
|
||||
public double RoundTime { get { return m.roundTime; } set { m.roundTime = ClampD(value); } }
|
||||
|
||||
[DisplayName("Flood time (mins)")]
|
||||
public double FloodTime { get { return m.floodTime; } set { m.floodTime = ClampD(value); } }
|
||||
|
||||
static byte Clamp(byte value) { return Math.Min(value, (byte)100); }
|
||||
static int ClampI(int value) { return Math.Max(0, Math.Min(value, 1000)); }
|
||||
static double ClampD(double value) { return Math.Max(0, Math.Min(value, 10)); }
|
||||
}
|
||||
}
|
||||
/*
|
||||
Copyright 2015 MCGalaxy
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using MCGalaxy.Games;
|
||||
|
||||
namespace MCGalaxy.Gui {
|
||||
public sealed class LavaMapProperties {
|
||||
internal readonly LSGame.MapSettings m;
|
||||
|
||||
public LavaMapProperties(LSGame.MapSettings m) {
|
||||
this.m = m;
|
||||
}
|
||||
|
||||
[DisplayName("Fast lava chance")]
|
||||
public byte FastLava { get { return m.fast; } set { m.fast = Clamp(value); } }
|
||||
|
||||
[DisplayName("Killer liquids chance")]
|
||||
public byte Killer { get { return m.killer; } set { m.killer = Clamp(value); } }
|
||||
|
||||
[DisplayName("Destroy blocks chance")]
|
||||
public byte Destroy { get { return m.destroy; } set { m.destroy = Clamp(value); } }
|
||||
|
||||
[DisplayName("Water flood chance")]
|
||||
public byte Water { get { return m.water; } set { m.water = Clamp(value); } }
|
||||
|
||||
[DisplayName("Layer flood chance")]
|
||||
public byte Layer { get { return m.layer; } set { m.layer = Clamp(value); } }
|
||||
|
||||
|
||||
[DisplayName("Layer height")]
|
||||
public int LayerHeight { get { return m.LayerHeight; } set { m.LayerHeight = ClampI(value); } }
|
||||
|
||||
[DisplayName("Layer count")]
|
||||
public int LayerCount { get { return m.LayerCount; } set { m.LayerCount = ClampI(value); } }
|
||||
|
||||
[DisplayName("Layer time (mins)")]
|
||||
public double LayerTime { get { return m.layerInterval; } set { m.layerInterval = ClampD(value); } }
|
||||
|
||||
[DisplayName("Round time (mins)")]
|
||||
public double RoundTime { get { return m.roundTime; } set { m.roundTime = ClampD(value); } }
|
||||
|
||||
[DisplayName("Flood time (mins)")]
|
||||
public double FloodTime { get { return m.floodTime; } set { m.floodTime = ClampD(value); } }
|
||||
|
||||
static byte Clamp(byte value) { return Math.Min(value, (byte)100); }
|
||||
static int ClampI(int value) { return Math.Max(0, Math.Min(value, 1000)); }
|
||||
static double ClampD(double value) { return Math.Max(0, Math.Min(value, 10)); }
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ namespace MCGalaxy.Blocks {
|
||||
}
|
||||
|
||||
internal static bool Train(Player p, BlockID block, ushort x, ushort y, ushort z) {
|
||||
if (!p.trainInvincible) p.HandleDeath(Block.Train);
|
||||
if (!p.trainInvincible && p.level.Config.KillerBlocks) p.HandleDeath(Block.Train);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
public static void PhysWater(Level lvl, ushort x, ushort y, ushort z, BlockID type) {
|
||||
int index;
|
||||
BlockID block = lvl.GetBlock(x, y, z, out index);
|
||||
if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
|
||||
if (Server.lava.running && Server.lava.Map == lvl && Server.lava.InSafeZone(x, y, z))
|
||||
return;
|
||||
|
||||
switch (block) {
|
||||
@ -62,7 +62,7 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
public static void PhysLava(Level lvl, ushort x, ushort y, ushort z, BlockID type) {
|
||||
int index;
|
||||
BlockID block = lvl.GetBlock(x, y, z, out index);
|
||||
if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
|
||||
if (Server.lava.running && Server.lava.Map == lvl && Server.lava.InSafeZone(x, y, z))
|
||||
return;
|
||||
|
||||
switch (block) {
|
||||
|
@ -149,7 +149,7 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
|
||||
static bool WaterBlocked(Level lvl, ushort x, ushort y, ushort z) {
|
||||
BlockID block = lvl.GetBlock(x, y, z);
|
||||
if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
|
||||
if (Server.lava.running && Server.lava.Map == lvl && Server.lava.InSafeZone(x, y, z))
|
||||
return true;
|
||||
|
||||
switch (block) {
|
||||
@ -261,7 +261,7 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
|
||||
static bool LavaBlocked(Level lvl, ushort x, ushort y, ushort z) {
|
||||
BlockID block = lvl.GetBlock(x, y, z);
|
||||
if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
|
||||
if (Server.lava.running && Server.lava.Map == lvl && Server.lava.InSafeZone(x, y, z))
|
||||
return true;
|
||||
|
||||
switch (block) {
|
||||
|
@ -30,7 +30,7 @@ namespace MCGalaxy {
|
||||
if (enable == CommandEnable.Economy && !Economy.Enabled)
|
||||
return "economy is disabled.";
|
||||
|
||||
if (enable == bothFlags && !(Server.zombie.Running || Server.lava.active))
|
||||
if (enable == bothFlags && !(Server.zombie.Running || Server.lava.running))
|
||||
return "neither zombie nor lava survival is running.";
|
||||
if (enable == CommandEnable.Zombie && !Server.zombie.Running)
|
||||
return "zombie survival is not running.";
|
||||
|
@ -72,10 +72,10 @@ namespace MCGalaxy.Commands.Fun {
|
||||
|
||||
void HandleStop(Player p) {
|
||||
if (!CheckExtraPerm(p, 1)) return;
|
||||
if (Server.ctf == null || !Server.ctf.started) {
|
||||
Player.Message(p, "No CTF game is active."); return;
|
||||
if (Server.ctf == null || !Server.ctf.Running) {
|
||||
Player.Message(p, "CTF is not running"); return;
|
||||
}
|
||||
Server.ctf.Stop();
|
||||
Server.ctf.End();
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,36 +34,36 @@ namespace MCGalaxy.Commands.Fun {
|
||||
public override void Use(Player p, string message) {
|
||||
if (message.Length == 0) { Help(p); return; }
|
||||
string[] args = message.ToLower().SplitSpaces();
|
||||
|
||||
LSGame game = Server.lava;
|
||||
|
||||
switch (args[0]) {
|
||||
case "go": HandleGo(p, args); return;
|
||||
case "info": HandleInfo(p, args); return;
|
||||
case "start": HandleStart(p, args); return;
|
||||
case "stop": HandleStop(p, args); return;
|
||||
case "end": HandleEnd(p, args); return;
|
||||
case "setup": HandleSetup(p, args); return;
|
||||
case "go": HandleGo(p, game); return;
|
||||
case "info": HandleInfo(p, game); return;
|
||||
case "start": HandleStart(p, args, game); return;
|
||||
case "stop": HandleStop(p, game); return;
|
||||
case "end": HandleEnd(p, game); return;
|
||||
case "setup": HandleSetup(p, args, game); return;
|
||||
}
|
||||
Help(p);
|
||||
}
|
||||
|
||||
void HandleGo(Player p, string[] args) {
|
||||
if (p == null) { Player.Message(p, "/{0} go can only be used in-game.", name); return; }
|
||||
if (!Server.lava.active) { Player.Message(p, "There is no Lava Survival game right now."); return; }
|
||||
PlayerActions.ChangeMap(p, Server.lava.map.name);
|
||||
void HandleGo(Player p, LSGame game) {
|
||||
if (!game.Running) { Player.Message(p, "Lava survival is not running"); return; }
|
||||
PlayerActions.ChangeMap(p, game.Map);
|
||||
}
|
||||
|
||||
void HandleInfo(Player p, string[] args) {
|
||||
if (!Server.lava.active) { Player.Message(p, "There is no Lava Survival game right now."); return; }
|
||||
if (!Server.lava.roundActive) { Player.Message(p, "The round of Lava Survival hasn't started yet."); return; }
|
||||
Server.lava.AnnounceRoundInfo(p, p == null);
|
||||
Server.lava.AnnounceTimeLeft(!Server.lava.flooded, true, p, p == null);
|
||||
void HandleInfo(Player p, LSGame game) {
|
||||
if (!game.Running) { Player.Message(p, "Lava survival is not running"); return; }
|
||||
if (!game.roundActive) { Player.Message(p, "The round of Lava Survival hasn't started yet."); return; }
|
||||
game.AnnounceRoundInfo(p, p == null);
|
||||
game.AnnounceTimeLeft(!game.flooded, true, p, p == null);
|
||||
}
|
||||
|
||||
void HandleStart(Player p, string[] args) {
|
||||
void HandleStart(Player p, string[] args, LSGame game) {
|
||||
if (!CheckExtraPerm(p, 1)) return;
|
||||
|
||||
string map = args.Length > 1 ? args[1] : "";
|
||||
switch (Server.lava.Start(map)) {
|
||||
switch (game.Start(map)) {
|
||||
case 0: Chat.MessageGlobal("Lava Survival has started! Join the fun with /ls go"); return;
|
||||
case 1: Player.Message(p, "There is already an active Lava Survival game."); return;
|
||||
case 2: Player.Message(p, "You must have at least 3 configured maps to play Lava Survival."); return;
|
||||
@ -72,142 +72,141 @@ namespace MCGalaxy.Commands.Fun {
|
||||
}
|
||||
}
|
||||
|
||||
void HandleStop(Player p, string[] args) {
|
||||
void HandleStop(Player p, LSGame game) {
|
||||
if (!CheckExtraPerm(p, 1)) return;
|
||||
|
||||
switch (Server.lava.Stop()) {
|
||||
case 0: Chat.MessageGlobal("Lava Survival has ended! We hope you had fun!"); return;
|
||||
case 1: Player.Message(p, "There isn't an active Lava Survival game."); return;
|
||||
default: Player.Message(p, "An unknown error occurred."); return;
|
||||
if (!game.Running) {
|
||||
Player.Message(p, "Lava survival is not running");
|
||||
} else {
|
||||
game.End();
|
||||
Chat.MessageGlobal("Lava Survival has ended! We hope you had fun!");
|
||||
}
|
||||
}
|
||||
|
||||
void HandleEnd(Player p, string[] args) {
|
||||
void HandleEnd(Player p, LSGame game) {
|
||||
if (!CheckExtraPerm(p, 1)) return;
|
||||
|
||||
if (!Server.lava.active) { Player.Message(p, "There isn't an active Lava Survival game."); return; }
|
||||
if (Server.lava.roundActive) Server.lava.EndRound();
|
||||
else if (Server.lava.voteActive) Server.lava.EndVote();
|
||||
if (!game.Running) { Player.Message(p, "Lava survival is not running"); return; }
|
||||
if (game.roundActive) game.EndRound();
|
||||
else if (game.voteActive) game.EndVote();
|
||||
else Player.Message(p, "There isn't an active round or vote to end.");
|
||||
}
|
||||
|
||||
void HandleSetup(Player p, string[] args) {
|
||||
void HandleSetup(Player p, string[] args, LSGame game) {
|
||||
if (!CheckExtraPerm(p, 1)) return;
|
||||
|
||||
if (p == null) { Player.Message(p, "/{0} setup can only be used in-game.", name); return; }
|
||||
if (args.Length < 2) { SetupHelp(p); return; }
|
||||
if (Server.lava.active) { Player.Message(p, "You cannot configure Lava Survival while a game is active."); return; }
|
||||
if (game.Running) { Player.Message(p, "You cannot configure Lava Survival while a game is active."); return; }
|
||||
string group = args[1];
|
||||
|
||||
if (group.CaselessEq("map")) {
|
||||
HandleSetupMap(p, args);
|
||||
HandleSetupMap(p, args, game);
|
||||
} else if (group.CaselessEq("block")) {
|
||||
HandleSetupBlock(p, args);
|
||||
HandleSetupBlock(p, args, game);
|
||||
} else if (group.CaselessEq("safe") || group.CaselessEq("safezone")) {
|
||||
HandleSetupSafeZone(p, args);
|
||||
HandleSetupSafeZone(p, args, game);
|
||||
} else if (group.CaselessEq("settings")) {
|
||||
HandleSetupSettings(p, args);
|
||||
HandleSetupSettings(p, args, game);
|
||||
} else if (group.CaselessEq("mapsettings")) {
|
||||
HandleSetupMapSettings(p, args);
|
||||
HandleSetupMapSettings(p, args, game);
|
||||
} else {
|
||||
SetupHelp(p);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleSetupMap(Player p, string[] args) {
|
||||
void HandleSetupMap(Player p, string[] args, LSGame game) {
|
||||
if (args.Length < 3) { SetupHelp(p, "map"); return; }
|
||||
Level lvl = Matcher.FindLevels(p, args[2]);
|
||||
if (lvl == null) return;
|
||||
if (lvl == Server.mainLevel) { Player.Message(p, "You cannot use the main map for Lava Survival."); return; }
|
||||
|
||||
if (Server.lava.HasMap(lvl.name)) {
|
||||
Server.lava.RemoveMap(lvl.name);
|
||||
if (game.HasMap(lvl.name)) {
|
||||
game.RemoveMap(lvl.name);
|
||||
lvl.Config.PhysicsOverload = 1500;
|
||||
lvl.Config.AutoUnload = true;
|
||||
lvl.Config.LoadOnGoto = true;
|
||||
Player.Message(p, "Map {0} %Shas been removed.", lvl.ColoredName);
|
||||
} else {
|
||||
Server.lava.AddMap(lvl.name);
|
||||
game.AddMap(lvl.name);
|
||||
|
||||
LavaSurvival.MapSettings settings = Server.lava.LoadMapSettings(lvl.name);
|
||||
settings.blockFlood = new Vec3U16((ushort)(lvl.Width / 2), (ushort)(lvl.Height - 1), (ushort)(lvl.Length / 2));
|
||||
settings.blockLayer = new Vec3U16(0, (ushort)(lvl.Height / 2), 0);
|
||||
LSGame.MapSettings settings = game.LoadMapSettings(lvl.name);
|
||||
settings.FloodPos = new Vec3U16((ushort)(lvl.Width / 2), (ushort)(lvl.Height - 1), (ushort)(lvl.Length / 2));
|
||||
settings.LayerPos = new Vec3U16(0, (ushort)(lvl.Height / 2), 0);
|
||||
ushort x = (ushort)(lvl.Width / 2), y = (ushort)(lvl.Height / 2), z = (ushort)(lvl.Length / 2);
|
||||
settings.safeZone = new Vec3U16[] { new Vec3U16((ushort)(x - 3), y, (ushort)(z - 3)), new Vec3U16((ushort)(x + 3), (ushort)(y + 4), (ushort)(z + 3)) };
|
||||
Server.lava.SaveMapSettings(settings);
|
||||
game.SaveMapSettings(settings);
|
||||
|
||||
lvl.Config.PhysicsOverload = 1000000;
|
||||
lvl.Config.AutoUnload = false;
|
||||
lvl.Config.LoadOnGoto = false;
|
||||
Player.Message(p, "Map {0} %Shas been added.", lvl.ColoredName);
|
||||
}
|
||||
Level.SaveSettings(lvl);
|
||||
}
|
||||
|
||||
void HandleSetupBlock(Player p, string[] args) {
|
||||
if (!Server.lava.HasMap(p.level.name)) { Player.Message(p, "Add the map before configuring it."); return; }
|
||||
void HandleSetupBlock(Player p, string[] args, LSGame game) {
|
||||
if (!game.HasMap(p.level.name)) { Player.Message(p, "Add the map before configuring it."); return; }
|
||||
if (args.Length < 3) { SetupHelp(p, "block"); return; }
|
||||
|
||||
if (args[2] == "flood") {
|
||||
Player.Message(p, "Place or destroy the block you want to be the total flood block spawn point.");
|
||||
p.MakeSelection(1, null, SetFloodPos);
|
||||
p.MakeSelection(1, game, SetFloodPos);
|
||||
} else if (args[2] == "layer") {
|
||||
Player.Message(p, "Place or destroy the block you want to be the layer flood base spawn point.");
|
||||
p.MakeSelection(1, null, SetFloodLayerPos);
|
||||
p.MakeSelection(1, game, SetFloodLayerPos);
|
||||
} else {
|
||||
SetupHelp(p, "block");
|
||||
}
|
||||
}
|
||||
|
||||
void HandleSetupSafeZone(Player p, string[] args) {
|
||||
void HandleSetupSafeZone(Player p, string[] args, LSGame game) {
|
||||
Player.Message(p, "Place or break two blocks to determine the edges.");
|
||||
p.MakeSelection(2, null, SetSafeZone);
|
||||
p.MakeSelection(2, game, SetSafeZone);
|
||||
}
|
||||
|
||||
void HandleSetupSettings(Player p, string[] args) {
|
||||
void HandleSetupSettings(Player p, string[] args, LSGame game) {
|
||||
if (args.Length < 3) {
|
||||
Player.Message(p, "Maps: &b" + Server.lava.Maps.Join(", "));
|
||||
Player.Message(p, "Start on server startup: " + (Server.lava.startOnStartup ? "&aON" : "&cOFF"));
|
||||
Player.Message(p, "Send AFK to main: " + (Server.lava.sendAfkMain ? "&aON" : "&cOFF"));
|
||||
Player.Message(p, "Vote count: &b" + Server.lava.voteCount);
|
||||
Player.Message(p, "Vote time: &b" + Server.lava.voteTime + " minutes");
|
||||
Player.Message(p, "Maps: &b" + game.Maps.Join(", "));
|
||||
Player.Message(p, "Start on server startup: " + (game.startOnStartup ? "&aON" : "&cOFF"));
|
||||
Player.Message(p, "Send AFK to main: " + (game.sendAfkMain ? "&aON" : "&cOFF"));
|
||||
Player.Message(p, "Vote count: &b" + game.voteCount);
|
||||
Player.Message(p, "Vote time: &b" + game.voteTime + " minutes");
|
||||
return;
|
||||
}
|
||||
|
||||
string opt = args[2], value = args.Length > 3 ? args[3] : "";
|
||||
TimeSpan span = default(TimeSpan);
|
||||
if (opt.CaselessEq("sendafkmain")) {
|
||||
Server.lava.sendAfkMain = !Server.lava.sendAfkMain;
|
||||
Player.Message(p, "Send AFK to main: " + (Server.lava.sendAfkMain ? "&aON" : "&cOFF"));
|
||||
game.sendAfkMain = !game.sendAfkMain;
|
||||
Player.Message(p, "Send AFK to main: " + (game.sendAfkMain ? "&aON" : "&cOFF"));
|
||||
} else if (opt.CaselessEq("votecount")) {
|
||||
if (!CommandParser.GetByte(p, value, "Count", ref Server.lava.voteCount, 2, 10)) return;
|
||||
Player.Message(p, "Vote count: &b" + Server.lava.voteCount);
|
||||
if (!CommandParser.GetByte(p, value, "Count", ref game.voteCount, 2, 10)) return;
|
||||
Player.Message(p, "Vote count: &b" + game.voteCount);
|
||||
} else if (opt.CaselessEq("votetime")) {
|
||||
if (!CommandParser.GetTimespan(p, value, ref span, "set time to", "m")) return;
|
||||
Server.lava.voteTime = span.TotalMinutes;
|
||||
game.voteTime = span.TotalMinutes;
|
||||
Player.Message(p, "Vote time: &b" + span.Shorten(true));
|
||||
} else {
|
||||
SetupHelp(p, "settings"); return;
|
||||
}
|
||||
Server.lava.SaveSettings();
|
||||
game.SaveSettings();
|
||||
}
|
||||
|
||||
void HandleSetupMapSettings(Player p, string[] args) {
|
||||
if (!Server.lava.HasMap(p.level.name)) { Player.Message(p, "Add the map before configuring it."); return; }
|
||||
LavaSurvival.MapSettings settings = Server.lava.LoadMapSettings(p.level.name);
|
||||
void HandleSetupMapSettings(Player p, string[] args, LSGame game) {
|
||||
if (!game.HasMap(p.level.name)) { Player.Message(p, "Add the map before configuring it."); return; }
|
||||
LSGame.MapSettings settings = game.LoadMapSettings(p.level.name);
|
||||
if (args.Length < 4) {
|
||||
Player.Message(p, "Fast lava chance: &b" + settings.fast + "%");
|
||||
Player.Message(p, "Killer lava/water chance: &b" + settings.killer + "%");
|
||||
Player.Message(p, "Destroy blocks chance: &b" + settings.destroy + "%");
|
||||
Player.Message(p, "Water flood chance: &b" + settings.water + "%");
|
||||
Player.Message(p, "Layer flood chance: &b" + settings.layer + "%");
|
||||
Player.Message(p, "Layer height: &b" + settings.layerHeight + " blocks");
|
||||
Player.Message(p, "Layer count: &b" + settings.layerCount);
|
||||
Player.Message(p, "Layer height: &b" + settings.LayerHeight + " blocks");
|
||||
Player.Message(p, "Layer count: &b" + settings.LayerCount);
|
||||
Player.Message(p, "Layer time: &b" + settings.layerInterval + " minutes");
|
||||
Player.Message(p, "Round time: &b" + settings.roundTime + " minutes");
|
||||
Player.Message(p, "Flood time: &b" + settings.floodTime + " minutes");
|
||||
Player.Message(p, "Flood position: &b" + settings.blockFlood.ToString(", "));
|
||||
Player.Message(p, "Layer position: &b" + settings.blockLayer.ToString(", "));
|
||||
Player.Message(p, "Flood position: &b" + settings.FloodPos.ToString(", "));
|
||||
Player.Message(p, "Layer position: &b" + settings.LayerPos.ToString(", "));
|
||||
Player.Message(p, "Safe zone: &b({0}) ({1})", settings.safeZone[0].ToString(", "), settings.safeZone[1].ToString(", "));
|
||||
return;
|
||||
}
|
||||
@ -235,12 +234,12 @@ namespace MCGalaxy.Commands.Fun {
|
||||
Player.Message(p, "Layer flood chance: &b" + settings.layer + "%");
|
||||
break;
|
||||
case "layerheight":
|
||||
settings.layerHeight = int.Parse(args[3]);
|
||||
Player.Message(p, "Layer height: &b" + settings.layerHeight + " blocks");
|
||||
settings.LayerHeight = int.Parse(args[3]);
|
||||
Player.Message(p, "Layer height: &b" + settings.LayerHeight + " blocks");
|
||||
break;
|
||||
case "layercount":
|
||||
settings.layerCount = int.Parse(args[3]);
|
||||
Player.Message(p, "Layer count: &b" + settings.layerCount);
|
||||
settings.LayerCount = int.Parse(args[3]);
|
||||
Player.Message(p, "Layer count: &b" + settings.LayerCount);
|
||||
break;
|
||||
case "layertime":
|
||||
settings.layerInterval = double.Parse(args[3]);
|
||||
@ -258,7 +257,7 @@ namespace MCGalaxy.Commands.Fun {
|
||||
SetupHelp(p, "mapsettings"); return;
|
||||
}
|
||||
} catch { Player.Message(p, "INVALID INPUT"); return; }
|
||||
Server.lava.SaveMapSettings(settings);
|
||||
game.SaveMapSettings(settings);
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
@ -313,18 +312,20 @@ namespace MCGalaxy.Commands.Fun {
|
||||
|
||||
|
||||
bool SetFloodPos(Player p, Vec3S32[] m, object state, BlockID block) {
|
||||
LavaSurvival.MapSettings settings = Server.lava.LoadMapSettings(p.level.name);
|
||||
settings.blockFlood = (Vec3U16)m[0];
|
||||
Server.lava.SaveMapSettings(settings);
|
||||
LSGame game = (LSGame)state;
|
||||
LSGame.MapSettings settings = game.LoadMapSettings(p.level.name);
|
||||
settings.FloodPos = (Vec3U16)m[0];
|
||||
game.SaveMapSettings(settings);
|
||||
|
||||
Player.Message(p, "Position set! &b({0}, {1}, {2})", m[0].X, m[0].Y, m[0].Z);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SetFloodLayerPos(Player p, Vec3S32[] m, object state, BlockID block) {
|
||||
LavaSurvival.MapSettings settings = Server.lava.LoadMapSettings(p.level.name);
|
||||
settings.blockLayer = (Vec3U16)m[0];
|
||||
Server.lava.SaveMapSettings(settings);
|
||||
LSGame game = (LSGame)state;
|
||||
LSGame.MapSettings settings = game.LoadMapSettings(p.level.name);
|
||||
settings.LayerPos = (Vec3U16)m[0];
|
||||
game.SaveMapSettings(settings);
|
||||
|
||||
Player.Message(p, "Position set! &b({0}, {1}, {2})", m[0].X, m[0].Y, m[0].Z);
|
||||
return false;
|
||||
@ -333,10 +334,11 @@ namespace MCGalaxy.Commands.Fun {
|
||||
bool SetSafeZone(Player p, Vec3S32[] m, object state, BlockID block) {
|
||||
Vec3S32 min = Vec3S32.Min(m[0], m[1]);
|
||||
Vec3S32 max = Vec3S32.Max(m[0], m[1]);
|
||||
LSGame game = (LSGame)state;
|
||||
|
||||
LavaSurvival.MapSettings settings = Server.lava.LoadMapSettings(p.level.name);
|
||||
LSGame.MapSettings settings = game.LoadMapSettings(p.level.name);
|
||||
settings.safeZone = new Vec3U16[] { (Vec3U16)min, (Vec3U16)max };
|
||||
Server.lava.SaveMapSettings(settings);
|
||||
game.SaveMapSettings(settings);
|
||||
|
||||
Player.Message(p, "Safe zone set! &b({0}, {1}, {2}) ({3}, {4}, {5})",
|
||||
min.X, min.Y, min.Z, max.X, max.Y, max.Z);
|
||||
|
@ -123,12 +123,11 @@ namespace MCGalaxy.Commands.Fun {
|
||||
Player pl = GetPlayer(args.player, pos, true);
|
||||
if (pl == null) return false;
|
||||
|
||||
BlockID stone = Block.Cobblestone;
|
||||
Player p = args.player;
|
||||
if (p.level.physics >= 3 && args.weaponType >= WeaponType.Explode) {
|
||||
pl.HandleDeath(stone, "@p %Swas blown up by " + p.ColoredName, true);
|
||||
pl.HandleDeath(Block.Cobblestone, "@p %Swas blown up by " + p.ColoredName, true);
|
||||
} else {
|
||||
pl.HandleDeath(stone, "@p %Swas hit by a missile from " + p.ColoredName);
|
||||
pl.HandleDeath(Block.Cobblestone, "@p %Swas hit by a missile from " + p.ColoredName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ namespace MCGalaxy.Commands.Fun {
|
||||
Player.Message(p, "Zombie Survival running, with " + (game.RoundsLeft + 1) + " rounds left"); break;
|
||||
}
|
||||
|
||||
Player.Message(p, "Running on map: " + game.MapName);
|
||||
Player.Message(p, "Running on map: " + game.Map.ColoredName);
|
||||
}
|
||||
|
||||
void HandleStart(Player p, ZSGame game, string[] args) {
|
||||
@ -97,18 +97,10 @@ namespace MCGalaxy.Commands.Fun {
|
||||
void HandleStop(Player p, ZSGame game) {
|
||||
if (!CheckExtraPerm(p, 1)) return;
|
||||
if (!game.Running) {
|
||||
Player.Message(p, "There is no Zombie Survival game currently in progress."); return;
|
||||
Player.Message(p, "Zombie Survival is not running");
|
||||
} else {
|
||||
game.End();
|
||||
}
|
||||
|
||||
string src = p == null ? "(console)" : p.ColoredName;
|
||||
Level lvl = game.Map;
|
||||
if (lvl != null) {
|
||||
Chat.MessageLevel(game.Map, "Zombie Survival was stopped by " + src);
|
||||
}
|
||||
|
||||
src = p == null ? "(console)" : p.name;
|
||||
Logger.Log(LogType.GameActivity, "Zombie Survival stopped by " + src);
|
||||
game.End();
|
||||
}
|
||||
|
||||
void HandleSet(Player p, ZSGame game, string[] args) {
|
||||
|
@ -132,11 +132,8 @@ namespace MCGalaxy.Commands.World {
|
||||
Group grp = Matcher.FindRanks(p, rank);
|
||||
if (grp != null) p.level.BuildAccess.SetMin(null, p.level, grp);
|
||||
} else if (cmd == "TEXTURE" || cmd == "TEXTUREZIP" || cmd == "TEXTUREPACK") {
|
||||
if (value.Length == 0) {
|
||||
Command.all.FindByName("Texture").Use(p, "levelzip normal");
|
||||
} else {
|
||||
Command.all.FindByName("Texture").Use(p, "levelzip " + value);
|
||||
}
|
||||
if (value.Length == 0) value = "normal";
|
||||
Command.all.FindByName("Texture").Use(p, "levelzip " + value);
|
||||
} else {
|
||||
cmd = LevelOptions.Map(cmd.ToLower());
|
||||
if (cmd == "physicspeed" || cmd == "overload" || cmd == "realmowner") {
|
||||
|
@ -30,7 +30,7 @@ namespace MCGalaxy.Core {
|
||||
if (cmd == "pony") {
|
||||
p.cancelcommand = true;
|
||||
if (!MessageCmd.CanSpeak(p, cmd)) return;
|
||||
int ponycount = p.Extras.GetInt("MCGalaxy_Core_Pony", 0);
|
||||
int ponycount = p.Extras.GetInt("MCGalaxy_Core_Pony", 0);
|
||||
|
||||
if (ponycount < 2) {
|
||||
Chat.MessageGlobal("{0} %Sjust so happens to be a proud brony! Everyone give {0} %Sa brohoof!", p.ColoredName);
|
||||
|
@ -180,7 +180,7 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
// Check to make sure the block is actually different and that we can change it
|
||||
if (old == b.Block || !lvl.CheckAffectPermissions(p, b.X, b.Y, b.Z, old, b.Block)) return;
|
||||
|
||||
// Set the block (inlined)
|
||||
// Set the block (inlined)
|
||||
lvl.Changed = true;
|
||||
if (b.Block >= Block.Extended) {
|
||||
#if TEN_BIT_BLOCKS
|
||||
|
@ -71,7 +71,7 @@ namespace MCGalaxy.Drawing.Ops {
|
||||
}
|
||||
}
|
||||
|
||||
private bool Axis(Vec3F32 P, Vec3F32 P1, Vec3F32 P2) {
|
||||
bool Axis(Vec3F32 P, Vec3F32 P1, Vec3F32 P2) {
|
||||
// Point to line segment test
|
||||
float bottom = (P2 - P1).LengthSquared;
|
||||
if (bottom == 0) return (P1 - P).Length <= 0.5f;
|
||||
|
@ -44,7 +44,6 @@ namespace MCGalaxy {
|
||||
/// <summary> Spawns this player to all other players that can see the player in the current world. </summary>
|
||||
public static void GlobalSpawn(Player p, Position pos, Orientation rot, bool self, string possession = "") {
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
p.Game.lastSpawnColor = p.Game.Infected ? ZSGame.InfectCol : p.color;
|
||||
TabList.Update(p, self);
|
||||
|
||||
foreach (Player other in players) {
|
||||
|
@ -99,13 +99,10 @@ namespace MCGalaxy.Events {
|
||||
Logger.LogError(ex);
|
||||
}
|
||||
|
||||
static string MethodFormat(string format, IMethod handler) {
|
||||
return String.Format(format, GetFullMethodName(handler), typeof(IMethod).Name);
|
||||
}
|
||||
|
||||
static string GetFullMethodName(object method) {
|
||||
static string MethodFormat(string format, IMethod method) {
|
||||
Delegate del = (Delegate)((object)method);
|
||||
return del.Method.ReflectedType.FullName + "." + del.Method.Name;
|
||||
string fullName = del.Method.ReflectedType.FullName + "." + del.Method.Name;
|
||||
return String.Format(format, fullName, typeof(IMethod).Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
39
MCGalaxy/Events/ServerEvents.cs
Normal file
39
MCGalaxy/Events/ServerEvents.cs
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MCGalaxy.Network;
|
||||
|
||||
namespace MCGalaxy.Events.ServerEvents {
|
||||
|
||||
public delegate void OnSendingHeartbeat(Heartbeat service, ref string name);
|
||||
public sealed class OnSendingHeartbeatEvent : IEvent<OnSendingHeartbeat> {
|
||||
|
||||
public static void Call(Heartbeat service, ref string name) {
|
||||
IEvent<OnSendingHeartbeat>[] items = handlers.Items;
|
||||
// Can't use CallCommon because we need to pass arguments by ref
|
||||
for (int i = 0; i < items.Length; i++) {
|
||||
try {
|
||||
items[i].method(service, ref name);
|
||||
} catch (Exception ex) {
|
||||
LogHandlerException(ex, items[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -25,13 +25,9 @@ using MCGalaxy.Maths;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
public sealed class CtfPlugin : Plugin_Simple {
|
||||
public override string creator { get { return Server.SoftwareName + " team"; } }
|
||||
public override string MCGalaxy_Version { get { return Server.VersionString; } }
|
||||
public override string name { get { return "Core_CTFPlugin"; } }
|
||||
public CTFGame Game;
|
||||
public sealed partial class CTFGame : RoundsGame {
|
||||
|
||||
public override void Load(bool startup) {
|
||||
void HookEventHandlers() {
|
||||
OnPlayerDeathEvent.Register(HandlePlayerDeath, Priority.High);
|
||||
OnPlayerChatEvent.Register(HandlePlayerChat, Priority.High);
|
||||
OnPlayerCommandEvent.Register(HandlePlayerCommand, Priority.High);
|
||||
@ -45,7 +41,7 @@ namespace MCGalaxy.Games {
|
||||
OnJoinedLevelEvent.Register(HandleOnJoinedLevel, Priority.High);
|
||||
}
|
||||
|
||||
public override void Unload(bool shutdown) {
|
||||
void UnhookEventHandlers() {
|
||||
OnPlayerDeathEvent.Unregister(HandlePlayerDeath);
|
||||
OnPlayerChatEvent.Unregister(HandlePlayerChat);
|
||||
OnPlayerCommandEvent.Unregister(HandlePlayerCommand);
|
||||
@ -61,38 +57,19 @@ namespace MCGalaxy.Games {
|
||||
|
||||
|
||||
void HandlePlayerDeath(Player p, BlockID deathblock) {
|
||||
if (!Game.started || p.level != Game.Map) return;
|
||||
if (!Game.Get(p).hasflag) return;
|
||||
if (!running || p.level != Map) return;
|
||||
if (!Get(p).hasflag) return;
|
||||
|
||||
CtfTeam2 team = Game.TeamOf(p);
|
||||
if (team != null) Game.DropFlag(p, team);
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
if (team != null) DropFlag(p, team);
|
||||
}
|
||||
|
||||
void HandlePlayerChat(Player p, string message) {
|
||||
if (Game.voting) {
|
||||
if (message == "1" || message.CaselessEq(Game.map1)) {
|
||||
Player.Message(p, "Thanks for voting :D");
|
||||
Game.vote1++;
|
||||
p.cancelchat = true;
|
||||
} else if (message == "2" || message.CaselessEq(Game.map2)) {
|
||||
Player.Message(p, "Thanks for voting :D");
|
||||
Game.vote2++;
|
||||
p.cancelchat = true;
|
||||
} else if (message == "3" || message.CaselessEq(Game.map3)) {
|
||||
Player.Message(p, "Thanks for voting :D");
|
||||
Game.vote3++;
|
||||
p.cancelchat = true;
|
||||
} else {
|
||||
Player.Message(p, "%2VOTE:");
|
||||
Player.Message(p, "1. " + Game.map1 + " 2. " + Game.map2 + " 3. " + Game.map3);
|
||||
p.cancelchat = true;
|
||||
}
|
||||
}
|
||||
if (Picker.HandlesMessage(p, message)) { p.cancelchat = true; return; }
|
||||
if (!running || p.level != Map) return;
|
||||
if (!Get(p).TeamChatting) return;
|
||||
|
||||
if (!Game.started || p.level != Game.Map) return;
|
||||
if (!Game.Get(p).TeamChatting) return;
|
||||
|
||||
CtfTeam2 team = Game.TeamOf(p);
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
if (team == null) return;
|
||||
Player[] members = team.Members.Items;
|
||||
|
||||
@ -103,8 +80,8 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
void HandleBlockChange(Player p, ushort x, ushort y, ushort z, BlockID block, bool placing) {
|
||||
if (!Game.started || p.level != Game.Map) return;
|
||||
CtfTeam2 team = Game.TeamOf(p);
|
||||
if (!running || p.level != Map) return;
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
if (team == null) {
|
||||
p.RevertBlock(x, y, z);
|
||||
Player.Message(p, "You are not on a team!");
|
||||
@ -113,43 +90,43 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
Vec3U16 pos = new Vec3U16(x, y, z);
|
||||
if (pos == Game.Opposing(team).FlagPos && !Game.Map.IsAirAt(x, y, z)) {
|
||||
Game.TakeFlag(p, team);
|
||||
if (pos == Opposing(team).FlagPos && !Map.IsAirAt(x, y, z)) {
|
||||
TakeFlag(p, team);
|
||||
}
|
||||
if (pos == team.FlagPos && !Game.Map.IsAirAt(x, y, z)) {
|
||||
Game.ReturnFlag(p, team);
|
||||
if (pos == team.FlagPos && !Map.IsAirAt(x, y, z)) {
|
||||
ReturnFlag(p, team);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleDisconnect(Player p, string reason) {
|
||||
if (p.level != Game.Map) return;
|
||||
CtfTeam2 team = Game.TeamOf(p);
|
||||
if (p.level != Map) return;
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
if (team == null) return;
|
||||
|
||||
Game.DropFlag(p, team);
|
||||
DropFlag(p, team);
|
||||
team.Remove(p);
|
||||
Chat.MessageLevel(Game.Map, team.Color + p.DisplayName + " %Sleft the ctf game");
|
||||
Chat.MessageLevel(Map, team.Color + p.DisplayName + " %Sleft the ctf game");
|
||||
}
|
||||
|
||||
void HandleLevelUnload(Level lvl) {
|
||||
if (Game.started && lvl == Game.Map) {
|
||||
if (running && lvl == Map) {
|
||||
Logger.Log(LogType.GameActivity, "Unload Failed!, A ctf game is currently going on!");
|
||||
lvl.cancelunload = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HandlePlayerSpawning(Player p, ref Position pos, ref byte yaw, ref byte pitch, bool respawning) {
|
||||
if (!Game.started || p.level != Game.Map) return;
|
||||
if (!running || p.level != Map) return;
|
||||
|
||||
CtfTeam2 team = Game.TeamOf(p);
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
if (team != null) pos = team.SpawnPos;
|
||||
if (team != null && respawning) Game.DropFlag(p, team);
|
||||
if (team != null && respawning) DropFlag(p, team);
|
||||
}
|
||||
|
||||
void HandleTabListEntryAdded(Entity entity, ref string tabName, ref string tabGroup, Player dst) {
|
||||
Player p = entity as Player;
|
||||
if (p == null || !Game.started || p.level != Game.Map) return;
|
||||
CtfTeam2 team = Game.TeamOf(p);
|
||||
if (p == null || !running || p.level != Map) return;
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
|
||||
if (p.Game.Referee) {
|
||||
tabGroup = "&2Referees";
|
||||
@ -161,31 +138,31 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
void HandleOnJoinedLevel(Player p, Level prevLevel, Level level) {
|
||||
if (p == null || !Game.started) return;
|
||||
if (p == null || !running) return;
|
||||
|
||||
if (prevLevel == Game.Map) {
|
||||
CtfTeam2 team = Game.TeamOf(p);
|
||||
if (prevLevel == Map) {
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
if (team == null) return;
|
||||
|
||||
Game.DropFlag(p, team);
|
||||
DropFlag(p, team);
|
||||
team.Remove(p);
|
||||
Chat.MessageLevel(Game.Map, team.Color + p.DisplayName + " %Sleft the ctf game");
|
||||
} else if (level == Game.Map) {
|
||||
if (Game.Blue.Members.Count > Game.Red.Members.Count) {
|
||||
Game.JoinTeam(p, Game.Red);
|
||||
} else if (Game.Red.Members.Count > Game.Blue.Members.Count) {
|
||||
Game.JoinTeam(p, Game.Blue);
|
||||
Chat.MessageLevel(Map, team.Color + p.DisplayName + " %Sleft the ctf game");
|
||||
} else if (level == Map) {
|
||||
if (Blue.Members.Count > Red.Members.Count) {
|
||||
JoinTeam(p, Red);
|
||||
} else if (Red.Members.Count > Blue.Members.Count) {
|
||||
JoinTeam(p, Blue);
|
||||
} else if (new Random().Next(2) == 0) {
|
||||
Game.JoinTeam(p, Game.Red);
|
||||
JoinTeam(p, Red);
|
||||
} else {
|
||||
Game.JoinTeam(p, Game.Blue);
|
||||
JoinTeam(p, Blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandlePlayerCommand(Player p, string cmd, string args) {
|
||||
if (!Game.started || p.level != Game.Map || cmd != "teamchat") return;
|
||||
CtfData data = Game.Get(p);
|
||||
if (!running || p.level != Map || cmd != "teamchat") return;
|
||||
CtfData data = Get(p);
|
||||
if (data == null) return;
|
||||
|
||||
if (data.TeamChatting) {
|
152
MCGalaxy/Games/CTF/CtfGame.Round.cs
Normal file
152
MCGalaxy/Games/CTF/CtfGame.Round.cs
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Written by fenderrock87
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Threading;
|
||||
using MCGalaxy.Maths;
|
||||
using MCGalaxy.SQL;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
public sealed partial class CTFGame : RoundsGame {
|
||||
|
||||
protected override void DoRound() {
|
||||
if (!running) return;
|
||||
RoundInProgress = true;
|
||||
|
||||
while (Blue.Points < Config.RoundPoints && Red.Points < Config.RoundPoints) {
|
||||
if (!running) return;
|
||||
if (!RoundInProgress) break;
|
||||
Tick();
|
||||
}
|
||||
|
||||
if (!running) return;
|
||||
EndRound();
|
||||
Picker.AddRecentMap(Map.MapName);
|
||||
|
||||
// TODO: Move players here
|
||||
if (RoundsLeft > 0) {
|
||||
string map = Picker.ChooseNextLevel(this);
|
||||
// (map != null) ChangeLevel(map);
|
||||
}
|
||||
}
|
||||
|
||||
void Tick() {
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player p in online) {
|
||||
if (p.level != Map) continue;
|
||||
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
if (team == null || Get(p).tagging) continue;
|
||||
if (!OnOwnTeamSide(p.Pos.BlockZ, team)) continue;
|
||||
CtfTeam2 opposing = Opposing(team);
|
||||
|
||||
Player[] opponents = opposing.Members.Items;
|
||||
foreach (Player other in opponents) {
|
||||
if (!MovementCheck.InRange(p, other, 2 * 32)) continue;
|
||||
|
||||
Get(other).tagging = true;
|
||||
Player.Message(other, p.ColoredName + " %Stagged you!");
|
||||
Command.all.FindByName("Spawn").Use(other, "");
|
||||
Thread.Sleep(300);
|
||||
|
||||
if (Get(other).hasflag) DropFlag(p, opposing);
|
||||
Get(p).Points += Config.Tag_PointsGained;
|
||||
Get(other).Points -= Config.Tag_PointsLost;
|
||||
Get(p).Tags++;
|
||||
Get(other).tagging = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void EndRound() {
|
||||
if (!RoundInProgress) return;
|
||||
RoundInProgress = false;
|
||||
|
||||
if (Blue.Points >= Config.RoundPoints || Blue.Points > Red.Points) {
|
||||
Chat.MessageLevel(Map, Blue.ColoredName + " %Swon this round of CTF!");
|
||||
} else if (Red.Points >= Config.RoundPoints || Red.Points > Blue.Points) {
|
||||
Chat.MessageLevel(Map, Red.ColoredName + " %Swon this round of CTF!");
|
||||
} else {
|
||||
Chat.MessageLevel(Map, "The round ended in a tie!");
|
||||
}
|
||||
|
||||
Thread.Sleep(4000);
|
||||
//MYSQL!
|
||||
cache.ForEach(delegate(CtfData d) {
|
||||
d.hasflag = false;
|
||||
Database.Backend.UpdateRows("CTF", "Points=@1, Captures=@2, tags=@3",
|
||||
"WHERE Name = @0", d.p.name, d.Points, d.Captures, d.Tags);
|
||||
});
|
||||
|
||||
Picker.AddRecentMap(Map.name);
|
||||
string nextMap = Picker.ChooseNextLevel(this);
|
||||
|
||||
Chat.MessageLevel(Map, "Starting a new game!");
|
||||
Blue.Members.Clear();
|
||||
Red.Members.Clear();
|
||||
Thread.Sleep(2000);
|
||||
SetMap(nextMap);
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Called when the given player takes the opposing team's flag. </summary>
|
||||
void TakeFlag(Player p, CtfTeam2 team) {
|
||||
CtfTeam2 opposing = Opposing(team);
|
||||
Chat.MessageLevel(Map, team.Color + p.DisplayName + " took the " + opposing.ColoredName + " %Steam's FLAG");
|
||||
Get(p).hasflag = true;
|
||||
}
|
||||
|
||||
/// <summary> Called when the given player, while holding opposing team's flag, clicks on their own flag. </summary>
|
||||
void ReturnFlag(Player p, CtfTeam2 team) {
|
||||
Vec3U16 flagPos = team.FlagPos;
|
||||
p.RevertBlock(flagPos.X, flagPos.Y, flagPos.Z);
|
||||
p.cancelBlock = true;
|
||||
|
||||
CtfData data = Get(p);
|
||||
if (data.hasflag) {
|
||||
Chat.MessageLevel(Map, team.Color + p.DisplayName + " RETURNED THE FLAG!");
|
||||
data.hasflag = false;
|
||||
data.Points += Config.Capture_PointsGained;
|
||||
data.Captures++;
|
||||
|
||||
CtfTeam2 opposing = Opposing(team);
|
||||
team.Points++;
|
||||
flagPos = opposing.FlagPos;
|
||||
Map.Blockchange(flagPos.X, flagPos.Y, flagPos.Z, opposing.FlagBlock);
|
||||
} else {
|
||||
Player.Message(p, "You cannot take your own flag!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Called when the given player drops the opposing team's flag. </summary>
|
||||
void DropFlag(Player p, CtfTeam2 team) {
|
||||
CtfData data = Get(p);
|
||||
if (!data.hasflag) return;
|
||||
|
||||
data.hasflag = false;
|
||||
Chat.MessageLevel(Map, team.Color + p.DisplayName + " DROPPED THE FLAG!");
|
||||
data.Points -= Config.Capture_PointsLost;
|
||||
|
||||
CtfTeam2 opposing = Opposing(team);
|
||||
Vec3U16 pos = opposing.FlagPos;
|
||||
Map.Blockchange(pos.X, pos.Y, pos.Z, opposing.FlagBlock);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ using System.Threading;
|
||||
using MCGalaxy.Commands.World;
|
||||
using MCGalaxy.Maths;
|
||||
using MCGalaxy.SQL;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
@ -33,35 +34,31 @@ namespace MCGalaxy.Games {
|
||||
public bool hasflag, tagging, TeamChatting;
|
||||
public CtfData(Player p) { this.p = p; }
|
||||
}
|
||||
|
||||
public sealed class CtfTeam2 {
|
||||
public string Name, Color;
|
||||
public string ColoredName { get { return Color + Name; } }
|
||||
public int Points;
|
||||
public Vec3U16 FlagPos;
|
||||
public Position SpawnPos;
|
||||
public BlockID FlagBlock;
|
||||
public VolatileArray<Player> Members = new VolatileArray<Player>();
|
||||
|
||||
public CtfTeam2(string name, string color) { Name = name; Color = color; }
|
||||
public bool Remove(Player p) { return Members.Remove(p); }
|
||||
}
|
||||
|
||||
public sealed partial class CTFGame : IGame {
|
||||
public System.Timers.Timer tagging = new System.Timers.Timer(500);
|
||||
public bool voting = false;
|
||||
internal int vote1 = 0, vote2 = 0, vote3 = 0;
|
||||
internal string map1 = "", map2 = "", map3 = "";
|
||||
public bool started = false;
|
||||
|
||||
/// <summary> Gets whether CTF is currently running. </summary>
|
||||
public override bool Running { get { return started; } }
|
||||
|
||||
public CtfTeam2 Red, Blue;
|
||||
List<CtfData> cache = new List<CtfData>();
|
||||
public sealed partial class CTFGame : RoundsGame {
|
||||
bool running = false;
|
||||
public override bool Running { get { return running; } }
|
||||
public override string GameName { get { return "CTF"; } }
|
||||
|
||||
public CtfTeam2 Red = new CtfTeam2("Red", Colors.red);
|
||||
public CtfTeam2 Blue = new CtfTeam2("Blue", Colors.blue);
|
||||
public CTFConfig Config = new CTFConfig();
|
||||
CtfPlugin plugin = new CtfPlugin();
|
||||
|
||||
/// <summary> Create a new CTF object </summary>
|
||||
public CTFGame() {
|
||||
Red = new CtfTeam2("Red", Colors.red);
|
||||
Blue = new CtfTeam2("Blue", Colors.blue);
|
||||
|
||||
tagging.Elapsed += CheckTagging;
|
||||
tagging.Start();
|
||||
plugin.Game = this;
|
||||
plugin.Load(false);
|
||||
}
|
||||
|
||||
|
||||
public LevelPicker Picker = new CTFLevelPicker();
|
||||
|
||||
List<CtfData> cache = new List<CtfData>();
|
||||
internal CtfData Get(Player p) {
|
||||
foreach (CtfData d in cache) {
|
||||
if (d.p == p) return d;
|
||||
@ -72,7 +69,6 @@ namespace MCGalaxy.Games {
|
||||
|
||||
/// <summary> Load a map into CTF </summary>
|
||||
public void SetMap(string mapName) {
|
||||
MapName = mapName;
|
||||
CmdLoad.LoadLevel(null, mapName);
|
||||
Map = LevelInfo.FindExact(mapName);
|
||||
Map.SaveChanges = false;
|
||||
@ -92,44 +88,7 @@ namespace MCGalaxy.Games {
|
||||
Blue.FlagPos = new Vec3U16((ushort)cfg.BlueFlagX, (ushort)cfg.BlueFlagY, (ushort)cfg.BlueFlagZ);
|
||||
Blue.SpawnPos = new Position(cfg.BlueSpawnX, cfg.BlueSpawnY, cfg.BlueSpawnZ);
|
||||
}
|
||||
|
||||
List<string> GetCtfMaps() {
|
||||
//Load some configs
|
||||
if (!Directory.Exists("CTF")) Directory.CreateDirectory("CTF");
|
||||
if (!File.Exists("CTF/maps.config")) return new List<string>();
|
||||
|
||||
string[] lines = File.ReadAllLines("CTF/maps.config");
|
||||
return new List<string>(lines);
|
||||
}
|
||||
|
||||
|
||||
void CheckTagging(object sender, System.Timers.ElapsedEventArgs e) {
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player p in online) {
|
||||
if (p.level != Map) continue;
|
||||
|
||||
CtfTeam2 team = TeamOf(p);
|
||||
if (team == null || Get(p).tagging) continue;
|
||||
if (!OnOwnTeamSide(p.Pos.BlockZ, team)) continue;
|
||||
CtfTeam2 opposing = Opposing(team);
|
||||
|
||||
Player[] opponents = opposing.Members.Items;
|
||||
foreach (Player other in opponents) {
|
||||
if (!MovementCheck.InRange(p, other, 2 * 32)) continue;
|
||||
|
||||
Get(other).tagging = true;
|
||||
Player.Message(other, p.ColoredName + " %Stagged you!");
|
||||
Command.all.FindByName("Spawn").Use(other, "");
|
||||
Thread.Sleep(300);
|
||||
|
||||
if (Get(other).hasflag) DropFlag(p, opposing);
|
||||
Get(p).Points += Config.Tag_PointsGained;
|
||||
Get(other).Points -= Config.Tag_PointsLost;
|
||||
Get(p).Tags++;
|
||||
Get(other).tagging = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ColumnDesc[] createSyntax = new ColumnDesc[] {
|
||||
new ColumnDesc("ID", ColumnType.Integer, priKey: true, autoInc: true, notNull: true),
|
||||
@ -141,147 +100,38 @@ namespace MCGalaxy.Games {
|
||||
|
||||
/// <summary> Start the CTF game </summary>
|
||||
public bool Start(Player p) {
|
||||
if (started) {
|
||||
if (running) {
|
||||
Player.Message(p, "CTF game already running."); return false;
|
||||
}
|
||||
|
||||
List<string> maps = GetCtfMaps();
|
||||
if (maps.Count == 0) {
|
||||
List<string> maps = Picker.GetCandidateMaps();
|
||||
if (maps == null || maps.Count == 0) {
|
||||
Player.Message(p, "No CTF maps were found."); return false;
|
||||
}
|
||||
|
||||
Blue = new CtfTeam2("Blue", Colors.blue);
|
||||
Red = new CtfTeam2("Red", Colors.red);
|
||||
SetMap(maps[new Random().Next(maps.Count)]);
|
||||
Red = new CtfTeam2("Red", Colors.red);
|
||||
|
||||
SetMap(LevelPicker.GetRandomMap(new Random(), maps));
|
||||
Logger.Log(LogType.GameActivity, "[CTF] Running...");
|
||||
started = true;
|
||||
running = true;
|
||||
Database.Backend.CreateTable("CTF", createSyntax);
|
||||
HookEventHandlers();
|
||||
|
||||
Thread t = new Thread(RunGame);
|
||||
t.Name = "MCG_CTFGame";
|
||||
t.Start();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> Stop the CTF game if running. </summary>
|
||||
public void Stop() {
|
||||
tagging.Stop();
|
||||
tagging.Dispose();
|
||||
public override void End() {
|
||||
running = false;
|
||||
RoundsLeft = 0;
|
||||
RoundInProgress = false;
|
||||
|
||||
UnhookEventHandlers();
|
||||
Picker.Clear();
|
||||
Map = null;
|
||||
started = false;
|
||||
}
|
||||
|
||||
string Vote() {
|
||||
started = false;
|
||||
vote1 = 0;
|
||||
vote2 = 0;
|
||||
vote3 = 0;
|
||||
Random rand = new Random();
|
||||
List<string> maps = GetCtfMaps();
|
||||
map1 = maps[rand.Next(maps.Count)];
|
||||
maps.Remove(map1);
|
||||
map2 = maps[rand.Next(maps.Count)];
|
||||
maps.Remove(map2);
|
||||
map3 = maps[rand.Next(maps.Count)];
|
||||
Chat.MessageLevel(Map, "%2VOTE:");
|
||||
Chat.MessageLevel(Map, "1. " + map1 + " 2. " + map2 + " 3. " + map3);
|
||||
voting = true;
|
||||
int seconds = rand.Next(15, 61);
|
||||
Chat.MessageLevel(Map, "You have " + seconds + " seconds to vote!");
|
||||
Thread.Sleep(seconds * 1000);
|
||||
voting = false;
|
||||
Chat.MessageLevel(Map, "VOTING ENDED!");
|
||||
Thread.Sleep(rand.Next(1, 10) * 1000);
|
||||
if (vote1 > vote2 && vote1 > vote3)
|
||||
{
|
||||
Chat.MessageLevel(Map, map1 + " WON!");
|
||||
return map1;
|
||||
}
|
||||
if (vote2 > vote1 && vote2 > vote3)
|
||||
{
|
||||
Chat.MessageLevel(Map, map2 + " WON!");
|
||||
return map2;
|
||||
}
|
||||
if (vote3 > vote2 && vote3 > vote1)
|
||||
{
|
||||
Chat.MessageLevel(Map, map3 + " WON!");
|
||||
return map3;
|
||||
}
|
||||
else
|
||||
{
|
||||
Chat.MessageLevel(Map, "There was a tie!");
|
||||
Chat.MessageLevel(Map, "I'll choose!");
|
||||
return maps[rand.Next(maps.Count)];
|
||||
}
|
||||
}
|
||||
|
||||
public override void EndRound() {
|
||||
started = false;
|
||||
if (Blue.Points >= Config.RoundPoints || Blue.Points > Red.Points) {
|
||||
Chat.MessageLevel(Map, Blue.ColoredName + " %Swon this round of CTF!");
|
||||
} else if (Red.Points >= Config.RoundPoints || Red.Points > Blue.Points) {
|
||||
Chat.MessageLevel(Map, Red.ColoredName + " %Swon this round of CTF!");
|
||||
} else {
|
||||
Chat.MessageLevel(Map, "The round ended in a tie!");
|
||||
}
|
||||
|
||||
Thread.Sleep(4000);
|
||||
//MYSQL!
|
||||
cache.ForEach(delegate(CtfData d) {
|
||||
d.hasflag = false;
|
||||
Database.Backend.UpdateRows("CTF", "Points=@1, Captures=@2, tags=@3",
|
||||
"WHERE Name = @0", d.p.name, d.Points, d.Captures, d.Tags);
|
||||
});
|
||||
|
||||
string nextmap = Vote();
|
||||
Chat.MessageLevel(Map, "Starting a new game!");
|
||||
Blue.Members.Clear();
|
||||
Red.Members.Clear();
|
||||
Thread.Sleep(2000);
|
||||
SetMap(nextmap);
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Called when the given player takes the opposing team's flag. </summary>
|
||||
public void TakeFlag(Player p, CtfTeam2 team) {
|
||||
CtfTeam2 opposing = Opposing(team);
|
||||
Chat.MessageLevel(Map, team.Color + p.DisplayName + " took the " + opposing.ColoredName + " %Steam's FLAG");
|
||||
Get(p).hasflag = true;
|
||||
}
|
||||
|
||||
/// <summary> Called when the given player, while holding opposing team's flag, clicks on their own flag. </summary>
|
||||
public void ReturnFlag(Player p, CtfTeam2 team) {
|
||||
Vec3U16 flagPos = team.FlagPos;
|
||||
p.RevertBlock(flagPos.X, flagPos.Y, flagPos.Z);
|
||||
p.cancelBlock = true;
|
||||
|
||||
CtfData data = Get(p);
|
||||
if (data.hasflag) {
|
||||
Chat.MessageLevel(Map, team.Color + p.DisplayName + " RETURNED THE FLAG!");
|
||||
data.hasflag = false;
|
||||
data.Points += Config.Capture_PointsGained;
|
||||
data.Captures++;
|
||||
|
||||
CtfTeam2 opposing = Opposing(team);
|
||||
team.Points++;
|
||||
flagPos = opposing.FlagPos;
|
||||
Map.Blockchange(flagPos.X, flagPos.Y, flagPos.Z, opposing.FlagBlock);
|
||||
|
||||
if (team.Points >= Config.RoundPoints) EndRound();
|
||||
} else {
|
||||
Player.Message(p, "You cannot take your own flag!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Called when the given player drops the opposing team's flag. </summary>
|
||||
public void DropFlag(Player p, CtfTeam2 team) {
|
||||
CtfData data = Get(p);
|
||||
if (!data.hasflag) return;
|
||||
|
||||
data.hasflag = false;
|
||||
Chat.MessageLevel(Map, team.Color + p.DisplayName + " DROPPED THE FLAG!");
|
||||
data.Points -= Config.Capture_PointsLost;
|
||||
|
||||
CtfTeam2 opposing = Opposing(team);
|
||||
Vec3U16 pos = opposing.FlagPos;
|
||||
Map.Blockchange(pos.X, pos.Y, pos.Z, opposing.FlagBlock);
|
||||
}
|
||||
|
||||
|
||||
@ -314,4 +164,22 @@ namespace MCGalaxy.Games {
|
||||
return team == Red ? Blue : Red;
|
||||
}
|
||||
}
|
||||
|
||||
internal class CTFLevelPicker : LevelPicker {
|
||||
|
||||
public override List<string> GetCandidateMaps() {
|
||||
List<string> maps = null;
|
||||
if (!Directory.Exists("CTF")) Directory.CreateDirectory("CTF");
|
||||
if (File.Exists("CTF/maps.config")) {
|
||||
string[] lines = File.ReadAllLines("CTF/maps.config");
|
||||
maps = new List<string>(lines);
|
||||
}
|
||||
|
||||
if (maps == null || maps.Count == 0) {
|
||||
Logger.Log(LogType.Warning, "You must have at least 1 level configured to play CTF");
|
||||
return null;
|
||||
}
|
||||
return maps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using MCGalaxy.Maths;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
/// <summary> Represents a team in Capture the Flag. </summary>
|
||||
public sealed class CtfTeam2 {
|
||||
|
||||
/// <summary> The name of this team. </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary> The color code of this team. </summary>
|
||||
public string Color;
|
||||
|
||||
public string ColoredName { get { return Color + Name; } }
|
||||
|
||||
/// <summary> Total points this team has collected. </summary>
|
||||
public int Points;
|
||||
|
||||
/// <summary> Players on this team. </summary>
|
||||
public VolatileArray<Player> Members = new VolatileArray<Player>();
|
||||
|
||||
|
||||
/// <summary> Position in the world the flag is located at. </summary>
|
||||
public Vec3U16 FlagPos;
|
||||
|
||||
/// <summary> Position in the world members of this team spawn at. </summary>
|
||||
public Position SpawnPos;
|
||||
|
||||
/// <summary> Block type of this team's flag. </summary>
|
||||
public BlockID FlagBlock;
|
||||
|
||||
public CtfTeam2(string name, string color) { Name = name; Color = color; }
|
||||
|
||||
|
||||
/// <summary> Removes a player from this team. </summary>
|
||||
public bool Remove(Player p) { return Members.Remove(p); }
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
@ -20,20 +20,17 @@ using MCGalaxy.Events.LevelEvents;
|
||||
using MCGalaxy.Events.PlayerEvents;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
public sealed class CountdownPlugin : Plugin_Simple {
|
||||
public override string creator { get { return Server.SoftwareName + " team"; } }
|
||||
public override string MCGalaxy_Version { get { return Server.VersionString; } }
|
||||
public override string name { get { return "Core_CountdownPlugin"; } }
|
||||
public CountdownGame Game;
|
||||
|
||||
public override void Load(bool startup) {
|
||||
|
||||
public sealed partial class CountdownGame : IGame {
|
||||
|
||||
void HookEventHandlers() {
|
||||
OnPlayerMoveEvent.Register(HandlePlayerMove, Priority.High);
|
||||
OnPlayerDisconnectEvent.Register(HandlePlayerDisconnect, Priority.High);
|
||||
OnLevelUnloadEvent.Register(HandleLevelUnload, Priority.High);
|
||||
OnPlayerSpawningEvent.Register(HandlePlayerSpawning, Priority.High);
|
||||
}
|
||||
|
||||
public override void Unload(bool shutdown) {
|
||||
void UnhookEventHandlers() {
|
||||
OnPlayerMoveEvent.Unregister(HandlePlayerMove);
|
||||
OnPlayerDisconnectEvent.Unregister(HandlePlayerDisconnect);
|
||||
OnLevelUnloadEvent.Unregister(HandleLevelUnload);
|
||||
@ -42,8 +39,8 @@ namespace MCGalaxy.Games {
|
||||
|
||||
|
||||
void HandlePlayerMove(Player p, Position next, byte yaw, byte pitch) {
|
||||
if (Game.Status != CountdownGameStatus.RoundInProgress || !Game.FreezeMode) return;
|
||||
if (!Game.Remaining.Contains(p)) return;
|
||||
if (Status != CountdownGameStatus.RoundInProgress || !FreezeMode) return;
|
||||
if (!Remaining.Contains(p)) return;
|
||||
|
||||
if (next.X != p.CountdownFreezeX || next.Z != p.CountdownFreezeZ) {
|
||||
next.X = p.CountdownFreezeX; next.Z = p.CountdownFreezeZ;
|
||||
@ -56,23 +53,23 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
void HandlePlayerDisconnect(Player p, string reason) {
|
||||
if (!Game.Players.Contains(p)) return;
|
||||
if (!Players.Contains(p)) return;
|
||||
|
||||
if (Game.Remaining.Contains(p)) {
|
||||
Game.Map.ChatLevel(p.ColoredName + " %Slogged out, and so is out of countdown");
|
||||
Game.PlayerLeftGame(p);
|
||||
if (Remaining.Contains(p)) {
|
||||
Map.ChatLevel(p.ColoredName + " %Slogged out, and so is out of countdown");
|
||||
PlayerLeftGame(p);
|
||||
}
|
||||
Game.Players.Remove(p);
|
||||
Players.Remove(p);
|
||||
}
|
||||
|
||||
void HandleLevelUnload(Level lvl) {
|
||||
if (Game.Status == CountdownGameStatus.Disabled || lvl != Game.Map) return;
|
||||
Game.Disable();
|
||||
}
|
||||
if (Status == CountdownGameStatus.Disabled || lvl != Map) return;
|
||||
Disable();
|
||||
}
|
||||
|
||||
void HandlePlayerSpawning(Player p, ref Position pos, ref byte yaw, ref byte pitch, bool respawning) {
|
||||
if (!respawning || !Game.Remaining.Contains(p)) return;
|
||||
Game.PlayerDied(p);
|
||||
if (!respawning || !Remaining.Contains(p)) return;
|
||||
PlayerDied(p);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,26 +19,40 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using MCGalaxy.Commands.World;
|
||||
using MCGalaxy.Events;
|
||||
using MCGalaxy.Events.LevelEvents;
|
||||
using MCGalaxy.Events.PlayerEvents;
|
||||
using MCGalaxy.Network;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
public sealed class CountdownGame : IGame {
|
||||
|
||||
public enum CountdownGameStatus {
|
||||
/// <summary> Countdown is not running. </summary>
|
||||
Disabled,
|
||||
/// <summary> Countdown is running, but no round has begun yet. </summary>
|
||||
Enabled,
|
||||
/// <summary> Timer is counting down to start of round. </summary>
|
||||
RoundCountdown,
|
||||
/// <summary> Round is in progress. </summary>
|
||||
RoundInProgress,
|
||||
}
|
||||
|
||||
public sealed partial class CountdownGame : IGame {
|
||||
|
||||
public VolatileArray<Player> Players = new VolatileArray<Player>();
|
||||
public VolatileArray<Player> Remaining = new VolatileArray<Player>();
|
||||
public CountdownGameStatus Status = CountdownGameStatus.Disabled;
|
||||
public CountdownGameStatus Status = CountdownGameStatus.Disabled;
|
||||
public override bool Running { get { return Status != CountdownGameStatus.Disabled; } }
|
||||
public override string GameName { get { return "Countdown"; } }
|
||||
|
||||
public bool FreezeMode = false;
|
||||
public bool FreezeMode;
|
||||
public int Interval;
|
||||
public string SpeedType;
|
||||
|
||||
CountdownPlugin plugin = new CountdownPlugin();
|
||||
List<SquarePos> squaresLeft = new List<SquarePos>();
|
||||
BufferedBlockSender bulk = new BufferedBlockSender();
|
||||
|
||||
|
||||
public override void EndRound() { EndRound(null); }
|
||||
|
||||
|
||||
@ -70,23 +84,23 @@ namespace MCGalaxy.Games {
|
||||
SpawnPlayers(xSpawn, ySpawn, zSpawn);
|
||||
Map.ChatLevel("-----&b5%S-----");
|
||||
|
||||
if (Status != CountdownGameStatus.RoundCountdown) return;
|
||||
if (Status != CountdownGameStatus.RoundCountdown) return;
|
||||
Cuboid(midX - 1, midY, midZ - 1, midX, midY, midZ, Block.Air);
|
||||
bulk.Send(true);
|
||||
Thread.Sleep(1000);
|
||||
|
||||
if (Status != CountdownGameStatus.RoundCountdown) return;
|
||||
if (Status != CountdownGameStatus.RoundCountdown) return;
|
||||
Map.ChatLevel("-----&b4%S-----"); Thread.Sleep(1000);
|
||||
Map.ChatLevel("-----&b3%S-----"); Thread.Sleep(1000);
|
||||
Cuboid(midX, Map.Height - 5, midZ, midX + 1, Map.Height - 5, midZ + 1, Block.Air);
|
||||
bulk.Send(true);
|
||||
|
||||
if (Status != CountdownGameStatus.RoundCountdown) return;
|
||||
if (Status != CountdownGameStatus.RoundCountdown) return;
|
||||
Map.ChatLevel("-----&b2%S-----"); Thread.Sleep(1000);
|
||||
Map.ChatLevel("-----&b1%S-----"); Thread.Sleep(1000);
|
||||
Map.ChatLevel("GO!!!!!!!");
|
||||
|
||||
if (Status != CountdownGameStatus.RoundCountdown) return;
|
||||
if (Status != CountdownGameStatus.RoundCountdown) return;
|
||||
Player[] players = Players.Items;
|
||||
Remaining.Clear();
|
||||
foreach (Player pl in players) { Remaining.Add(pl); }
|
||||
@ -323,10 +337,7 @@ namespace MCGalaxy.Games {
|
||||
|
||||
|
||||
public void Enable(Player p) {
|
||||
plugin.Game = this;
|
||||
plugin.Load(false);
|
||||
|
||||
MapName = "countdown";
|
||||
HookEventHandlers();
|
||||
CmdLoad.LoadLevel(null, "countdown");
|
||||
Map = LevelInfo.FindExact("countdown");
|
||||
|
||||
@ -347,10 +358,9 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
public void Disable() {
|
||||
if (Status == CountdownGameStatus.RoundInProgress) EndRound(null);
|
||||
|
||||
if (Status == CountdownGameStatus.RoundInProgress) EndRound(null);
|
||||
Status = CountdownGameStatus.Disabled;
|
||||
plugin.Unload(false);
|
||||
UnhookEventHandlers();
|
||||
|
||||
Map.ChatLevel("Countdown was disabled.");
|
||||
Players.Clear();
|
||||
@ -397,11 +407,11 @@ namespace MCGalaxy.Games {
|
||||
Cuboid(midX - 1, midY + 1, midZ + 1, midX, midY + 2, midZ + 1, block);
|
||||
Cuboid(midX - 2, midY + 1, midZ - 1, midX - 2, midY + 2, midZ, block);
|
||||
Cuboid(midX + 1, midY + 1, midZ - 1, midX + 1, midY + 2, midZ, block);
|
||||
Cuboid(midX - 1, midY, midZ - 1, midX, midY, midZ, floorBlock);
|
||||
Cuboid(midX - 1, midY, midZ - 1, midX, midY, midZ, floorBlock);
|
||||
bulk.Send(true);
|
||||
}
|
||||
|
||||
void Cuboid(int x1, int y1, int z1, int x2, int y2, int z2, BlockID block) {
|
||||
void Cuboid(int x1, int y1, int z1, int x2, int y2, int z2, BlockID block) {
|
||||
for (int y = y1; y <= y2; y++)
|
||||
for (int z = z1; z <= z2; z++)
|
||||
for (int x = x1; x <= x2; x++)
|
||||
@ -437,18 +447,4 @@ namespace MCGalaxy.Games {
|
||||
UpdatePlayersLeft();
|
||||
}
|
||||
}
|
||||
|
||||
public enum CountdownGameStatus {
|
||||
/// <summary> Countdown is not running. </summary>
|
||||
Disabled,
|
||||
|
||||
/// <summary> Countdown is running, but no round has begun yet. </summary>
|
||||
Enabled,
|
||||
|
||||
/// <summary> Timer is counting down to start of round. </summary>
|
||||
RoundCountdown,
|
||||
|
||||
/// <summary> Round is in progress. </summary>
|
||||
RoundInProgress,
|
||||
}
|
||||
}
|
||||
|
@ -60,9 +60,6 @@ namespace MCGalaxy.Games {
|
||||
/// <summary> Whether the real names of zombies are always shown to the player. </summary>
|
||||
public bool Aka = false;
|
||||
|
||||
/// <summary> Last name color sent to other players from a call to GlobalSpawn. </summary>
|
||||
internal string lastSpawnColor = "";
|
||||
|
||||
/// <summary> List of custom infect messages this player has. </summary>
|
||||
internal List<string> InfectMessages = null;
|
||||
|
||||
|
@ -20,32 +20,34 @@ using System;
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
public abstract class IGame {
|
||||
public string MapName;
|
||||
public Level Map;
|
||||
public abstract bool Running { get; }
|
||||
|
||||
/// <summary> Whether players are allowed to teleport to others when not in referee mode. </summary>
|
||||
public abstract string GameName { get; }
|
||||
public virtual bool TeleportAllowed { get { return true; } }
|
||||
/// <summary> Returns whether this game handled the player sending a chat message. </summary>
|
||||
public virtual bool HandlesChatMessage(Player p, string message) { return false; }
|
||||
|
||||
public virtual void PlayerJoinedServer(Player p) { }
|
||||
|
||||
public virtual bool HandlesChatMessage(Player p, string message) { return false; }
|
||||
public virtual void PlayerJoinedGame(Player p) { }
|
||||
public virtual void PlayerLeftGame(Player p) { }
|
||||
public virtual void PlayerJoinedLevel(Player p, Level lvl, Level oldLvl) { }
|
||||
public virtual void OnHeartbeat(ref string name) { }
|
||||
|
||||
/// <summary> Adjusts the prefix (e.g. title) shown before the player's name in chat. </summary>
|
||||
public virtual void AdjustPrefix(Player p, ref string prefix) { }
|
||||
|
||||
public virtual void AdjustPrefix(Player p, ref string prefix) { }
|
||||
public abstract void EndRound();
|
||||
|
||||
public void MessageMap(CpeMessageType type, string message) {
|
||||
if (!Running) return;
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
|
||||
foreach (Player p in online) {
|
||||
if (p.level != Map) continue;
|
||||
p.SendCpeMessage(type, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class RoundsGame : IGame {
|
||||
public int RoundsLeft;
|
||||
public bool RoundInProgress;
|
||||
|
||||
public abstract string GameName { get; }
|
||||
public abstract void End();
|
||||
protected abstract void DoRound();
|
||||
|
||||
|
@ -23,15 +23,15 @@ using MCGalaxy.Maths;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
public sealed partial class LavaSurvival {
|
||||
public sealed partial class LSGame : RoundsGame {
|
||||
|
||||
public MapData GenerateMapData(MapSettings settings) {
|
||||
MapData data = new MapData(settings);
|
||||
data.killer = rand.Next(1, 101) <= settings.killer;
|
||||
data.killer = rand.Next(1, 101) <= settings.killer;
|
||||
data.destroy = rand.Next(1, 101) <= settings.destroy;
|
||||
data.water = rand.Next(1, 101) <= settings.water;
|
||||
data.layer = rand.Next(1, 101) <= settings.layer;
|
||||
data.fast = rand.Next(1, 101) <= settings.fast && !data.water;
|
||||
data.water = rand.Next(1, 101) <= settings.water;
|
||||
data.layer = rand.Next(1, 101) <= settings.layer;
|
||||
data.fast = rand.Next(1, 101) <= settings.fast && !data.water;
|
||||
|
||||
byte block = data.water ? (data.killer ? Block.Deadly_ActiveWater : Block.Water)
|
||||
: (data.fast ? (data.killer ? Block.Deadly_FastLava : Block.FastLava)
|
||||
@ -99,8 +99,8 @@ namespace MCGalaxy.Games {
|
||||
|
||||
public MapSettings LoadMapSettings(string name) {
|
||||
MapSettings settings = new MapSettings(name);
|
||||
if (!Directory.Exists(propsPath)) Directory.CreateDirectory(propsPath);
|
||||
string path = propsPath + name + ".properties";
|
||||
if (!Directory.Exists(propsDir)) Directory.CreateDirectory(propsDir);
|
||||
string path = propsDir + name + ".properties";
|
||||
if (!File.Exists(path)) { SaveMapSettings(settings); return settings; }
|
||||
|
||||
try {
|
||||
@ -112,55 +112,47 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
void ProcessMapLine(string key, string value, ref MapSettings map) {
|
||||
string[] sp;
|
||||
switch (key.ToLower()) {
|
||||
case "fast-chance": map.fast = (byte)Utils.Clamp(int.Parse(value), 0, 100); break;
|
||||
case "killer-chance": map.killer = (byte)Utils.Clamp(int.Parse(value), 0, 100); break;
|
||||
case "destroy-chance": map.destroy = (byte)Utils.Clamp(int.Parse(value), 0, 100); break;
|
||||
case "water-chance": map.water = (byte)Utils.Clamp(int.Parse(value), 0, 100); break;
|
||||
case "layer-chance": map.layer = (byte)Utils.Clamp(int.Parse(value), 0, 100); break;
|
||||
case "layer-height": map.layerHeight = int.Parse(value); break;
|
||||
case "layer-count": map.layerCount = int.Parse(value); break;
|
||||
case "layer-height": map.LayerHeight = int.Parse(value); break;
|
||||
case "layer-count": map.LayerCount = int.Parse(value); break;
|
||||
case "layer-interval": map.layerInterval = double.Parse(value); break;
|
||||
case "round-time": map.roundTime = double.Parse(value); break;
|
||||
case "flood-time": map.floodTime = double.Parse(value); break;
|
||||
|
||||
case "block-flood":
|
||||
sp = value.Split(',');
|
||||
map.blockFlood = new Vec3U16(ushort.Parse(sp[0]), ushort.Parse(sp[1]), ushort.Parse(sp[2]));
|
||||
break;
|
||||
map.FloodPos = Vec3U16.Parse(value); break;
|
||||
case "block-layer":
|
||||
sp = value.Split(',');
|
||||
map.blockLayer = new Vec3U16(ushort.Parse(sp[0]), ushort.Parse(sp[1]), ushort.Parse(sp[2]));
|
||||
break;
|
||||
map.LayerPos = Vec3U16.Parse(value); break;
|
||||
case "safe-zone":
|
||||
sp = value.Split('-');
|
||||
string[] p1 = sp[0].Split(','), p2 = sp[1].Split(',');
|
||||
map.safeZone = new Vec3U16[] {
|
||||
new Vec3U16(ushort.Parse(p1[0]), ushort.Parse(p1[1]), ushort.Parse(p1[2])),
|
||||
new Vec3U16(ushort.Parse(p2[0]), ushort.Parse(p2[1]), ushort.Parse(p2[2])) };
|
||||
string[] p = value.Split('-');
|
||||
map.safeZone = new Vec3U16[] { Vec3U16.Parse(p[0]), Vec3U16.Parse(p[1]) };
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveMapSettings(MapSettings settings) {
|
||||
if (!Directory.Exists(propsPath)) Directory.CreateDirectory(propsPath);
|
||||
if (!Directory.Exists(propsDir)) Directory.CreateDirectory(propsDir);
|
||||
|
||||
using (StreamWriter w = new StreamWriter(propsPath + settings.name + ".properties")) {
|
||||
using (StreamWriter w = new StreamWriter(propsDir + settings.name + ".properties")) {
|
||||
w.WriteLine("#Lava Survival properties for " + settings.name);
|
||||
w.WriteLine("fast-chance = " + settings.fast);
|
||||
w.WriteLine("killer-chance = " + settings.killer);
|
||||
w.WriteLine("destroy-chance = " + settings.destroy);
|
||||
w.WriteLine("water-chance = " + settings.water);
|
||||
w.WriteLine("layer-chance = " + settings.layer);
|
||||
w.WriteLine("layer-height = " + settings.layerHeight);
|
||||
w.WriteLine("layer-count = " + settings.layerCount);
|
||||
w.WriteLine("layer-height = " + settings.LayerHeight);
|
||||
w.WriteLine("layer-count = " + settings.LayerCount);
|
||||
w.WriteLine("layer-interval = " + settings.layerInterval);
|
||||
w.WriteLine("round-time = " + settings.roundTime);
|
||||
w.WriteLine("flood-time = " + settings.floodTime);
|
||||
w.WriteLine("block-flood = " + settings.blockFlood);
|
||||
w.WriteLine("block-layer = " + settings.blockLayer);
|
||||
w.WriteLine(String.Format("safe-zone = {0}-{1}", settings.safeZone[0].ToString(), settings.safeZone[1].ToString()));
|
||||
w.WriteLine("block-flood = " + settings.FloodPos);
|
||||
w.WriteLine("block-layer = " + settings.LayerPos);
|
||||
w.WriteLine("safe-zone = " + settings.safeZone[0] + " - " + settings.safeZone[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,9 +161,9 @@ namespace MCGalaxy.Games {
|
||||
{
|
||||
public string name;
|
||||
public byte fast, killer, destroy, water, layer;
|
||||
public int layerHeight, layerCount;
|
||||
public int LayerHeight, LayerCount;
|
||||
public double layerInterval, roundTime, floodTime;
|
||||
public Vec3U16 blockFlood, blockLayer;
|
||||
public Vec3U16 FloodPos, LayerPos;
|
||||
public Vec3U16[] safeZone;
|
||||
|
||||
public MapSettings(string name)
|
||||
@ -182,13 +174,13 @@ namespace MCGalaxy.Games {
|
||||
destroy = 0;
|
||||
water = 0;
|
||||
layer = 0;
|
||||
layerHeight = 3;
|
||||
layerCount = 10;
|
||||
LayerHeight = 3;
|
||||
LayerCount = 10;
|
||||
layerInterval = 2;
|
||||
roundTime = 15;
|
||||
floodTime = 5;
|
||||
blockFlood = new Vec3U16();
|
||||
blockLayer = new Vec3U16();
|
||||
FloodPos = new Vec3U16();
|
||||
LayerPos = new Vec3U16();
|
||||
safeZone = new Vec3U16[2];
|
||||
}
|
||||
}
|
60
MCGalaxy/Games/LavaSurvival/LSGame.Plugin.cs
Normal file
60
MCGalaxy/Games/LavaSurvival/LSGame.Plugin.cs
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using MCGalaxy.Events;
|
||||
using MCGalaxy.Events.PlayerEvents;
|
||||
using MCGalaxy.Events.LevelEvents;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
public sealed partial class LSGame : RoundsGame {
|
||||
|
||||
void HookEventHandlers() {
|
||||
OnLevelUnloadEvent.Register(HandleLevelUnload, Priority.High);
|
||||
|
||||
OnPlayerConnectEvent.Register(HandlePlayerConnect, Priority.High);
|
||||
OnPlayerDeathEvent.Register(HandlePlayerDeath, Priority.High);
|
||||
}
|
||||
|
||||
void UnhookEventHandlers() {
|
||||
OnLevelUnloadEvent.Unregister(HandleLevelUnload);
|
||||
|
||||
OnPlayerConnectEvent.Unregister(HandlePlayerConnect);
|
||||
OnPlayerDeathEvent.Unregister(HandlePlayerDeath);
|
||||
}
|
||||
|
||||
|
||||
void HandleLevelUnload(Level lvl) {
|
||||
if (lvl == Map) lvl.cancelunload = true;
|
||||
}
|
||||
|
||||
void HandlePlayerConnect(Player p) {
|
||||
Player.Message(p, "&cLava Survival %Sis running! Type %T/ls go %Sto join");
|
||||
}
|
||||
|
||||
void HandlePlayerDeath(Player p, BlockID block) {
|
||||
if (p.level != Map) return;
|
||||
|
||||
if (IsPlayerDead(p)) {
|
||||
p.cancelDeath = true;
|
||||
} else {
|
||||
KillPlayer(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,426 +1,291 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
using MCGalaxy.Commands.World;
|
||||
using MCGalaxy.Maths;
|
||||
|
||||
namespace MCGalaxy.Games
|
||||
{
|
||||
public sealed partial class LavaSurvival
|
||||
{
|
||||
// Private variables
|
||||
private string propsPath = "properties/lavasurvival/";
|
||||
private List<string> maps, voted;
|
||||
private Dictionary<string, int> votes, deaths;
|
||||
private Random rand = new Random();
|
||||
private Timer announceTimer, voteTimer, transferTimer;
|
||||
private DateTime startTime;
|
||||
|
||||
// Public variables
|
||||
public bool active = false, roundActive = false, flooded = false, voteActive = false, sendingPlayers = false;
|
||||
public Level map;
|
||||
public MapSettings mapSettings;
|
||||
public MapData mapData;
|
||||
|
||||
/// <summary> Gets whether lava survival is currently running. </summary>
|
||||
public override bool Running { get { return active; } }
|
||||
|
||||
// Settings
|
||||
public bool startOnStartup, sendAfkMain = true;
|
||||
public byte voteCount = 2;
|
||||
public int lifeNum = 3;
|
||||
public double voteTime = 2;
|
||||
|
||||
// Constructors
|
||||
public LavaSurvival() {
|
||||
maps = new List<string>();
|
||||
voted = new List<string>();
|
||||
votes = new Dictionary<string, int>();
|
||||
deaths = new Dictionary<string, int>();
|
||||
announceTimer = new Timer(60000);
|
||||
announceTimer.AutoReset = true;
|
||||
announceTimer.Elapsed += delegate
|
||||
{
|
||||
if (!flooded) AnnounceTimeLeft(true, false);
|
||||
};
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
// Public methods
|
||||
public byte Start(string mapName = "")
|
||||
{
|
||||
if (active) return 1; // Already started
|
||||
if (maps.Count < 3) return 2; // Not enough maps
|
||||
if (!String.IsNullOrEmpty(mapName) && !HasMap(mapName)) return 3; // Map doesn't exist
|
||||
|
||||
deaths.Clear();
|
||||
active = true;
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Game started.");
|
||||
|
||||
try { LoadMap(String.IsNullOrEmpty(mapName) ? maps[rand.Next(maps.Count)] : mapName); }
|
||||
catch (Exception e) { Logger.LogError(e); active = false; return 4; }
|
||||
return 0;
|
||||
}
|
||||
public byte Stop()
|
||||
{
|
||||
if (!active) return 1; // Not started
|
||||
|
||||
active = false;
|
||||
roundActive = false;
|
||||
voteActive = false;
|
||||
flooded = false;
|
||||
deaths.Clear();
|
||||
if (announceTimer.Enabled) announceTimer.Stop();
|
||||
try { mapData.Dispose(); }
|
||||
catch { }
|
||||
try { voteTimer.Dispose(); }
|
||||
catch { }
|
||||
try { transferTimer.Dispose(); }
|
||||
catch { }
|
||||
map.Unload(true, false);
|
||||
map = null;
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Game stopped.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void StartRound()
|
||||
{
|
||||
if (roundActive) return;
|
||||
|
||||
try
|
||||
{
|
||||
deaths.Clear();
|
||||
mapData.roundTimer.Elapsed += delegate { EndRound(); };
|
||||
mapData.floodTimer.Elapsed += delegate { DoFlood(); };
|
||||
mapData.roundTimer.Start();
|
||||
mapData.floodTimer.Start();
|
||||
announceTimer.Start();
|
||||
startTime = DateTime.UtcNow;
|
||||
roundActive = true;
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Round started. Map: " + map.ColoredName);
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
}
|
||||
|
||||
public override void EndRound()
|
||||
{
|
||||
if (!roundActive) return;
|
||||
|
||||
roundActive = false;
|
||||
flooded = false;
|
||||
try
|
||||
{
|
||||
try { mapData.Dispose(); }
|
||||
catch { }
|
||||
map.SetPhysics(5);
|
||||
map.ChatLevel("The round has ended!");
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Round ended. Voting...");
|
||||
StartVote();
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
}
|
||||
|
||||
public void DoFlood()
|
||||
{
|
||||
if (!active || !roundActive || flooded || map == null) return;
|
||||
flooded = true;
|
||||
|
||||
try
|
||||
{
|
||||
announceTimer.Stop();
|
||||
map.ChatLevel("&4Look out, here comes the flood!");
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Map flooding.");
|
||||
if (mapData.layer)
|
||||
{
|
||||
DoFloodLayer();
|
||||
mapData.layerTimer.Elapsed += delegate
|
||||
{
|
||||
if (mapData.currentLayer <= mapSettings.layerCount)
|
||||
{
|
||||
DoFloodLayer();
|
||||
}
|
||||
else
|
||||
mapData.layerTimer.Stop();
|
||||
};
|
||||
mapData.layerTimer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
map.Blockchange(mapSettings.blockFlood.X, mapSettings.blockFlood.Y, mapSettings.blockFlood.Z, mapData.block, true);
|
||||
}
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
}
|
||||
|
||||
void DoFloodLayer() {
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Layer " + mapData.currentLayer + " flooding.");
|
||||
map.Blockchange(mapSettings.blockLayer.X, (ushort)(mapSettings.blockLayer.Y + ((mapSettings.layerHeight * mapData.currentLayer) - 1)), mapSettings.blockLayer.Z, mapData.block, true);
|
||||
mapData.currentLayer++;
|
||||
}
|
||||
|
||||
public void AnnounceTimeLeft(bool flood, bool round, Player p = null, bool console = false) {
|
||||
if (!active || !roundActive || startTime == null || map == null) return;
|
||||
|
||||
if (flood) {
|
||||
double floodMinutes = Math.Ceiling((startTime.AddMinutes(mapSettings.floodTime) - DateTime.UtcNow).TotalMinutes);
|
||||
if (p == null && !console) map.ChatLevel("&3" + floodMinutes + " minute" + (floodMinutes == 1 ? "" : "s") + " %Suntil the flood.");
|
||||
else Player.Message(p, "&3" + floodMinutes + " minute" + (floodMinutes == 1 ? "" : "s") + " %Suntil the flood.");
|
||||
}
|
||||
if (round) {
|
||||
double roundMinutes = Math.Ceiling((startTime.AddMinutes(mapSettings.roundTime) - DateTime.UtcNow).TotalMinutes);
|
||||
if (p == null && !console) map.ChatLevel("&3" + roundMinutes + " minute" + (roundMinutes == 1 ? "" : "s") + " %Suntil the round ends.");
|
||||
else Player.Message(p, "&3" + roundMinutes + " minute" + (roundMinutes == 1 ? "" : "s") + " %Suntil the round ends.");
|
||||
}
|
||||
}
|
||||
|
||||
public void AnnounceRoundInfo(Player p = null, bool console = false) {
|
||||
if (p == null && !console) {
|
||||
if (mapData.water) map.ChatLevel("The map will be flooded with &9water %Sthis round!");
|
||||
if (mapData.layer)
|
||||
{
|
||||
map.ChatLevel("The " + (mapData.water ? "water" : "lava") + " will &aflood in layers %Sthis round!");
|
||||
map.ChatLevelOps("There will be " + mapSettings.layerCount + " layers, each " + mapSettings.layerHeight + " blocks high.");
|
||||
map.ChatLevelOps("There will be another layer every " + mapSettings.layerInterval + " minutes.");
|
||||
}
|
||||
if (mapData.fast) map.ChatLevel("The lava will be &cfast %Sthis round!");
|
||||
if (mapData.killer) map.ChatLevel("The " + (mapData.water ? "water" : "lava") + " will &ckill you %Sthis round!");
|
||||
if (mapData.destroy) map.ChatLevel("The " + (mapData.water ? "water" : "lava") + " will &cdestroy plants " + (mapData.water ? "" : "and flammable blocks ") + "%Sthis round!");
|
||||
} else {
|
||||
if (mapData.water) Player.Message(p, "The map will be flooded with &9water %Sthis round!");
|
||||
if (mapData.layer) Player.Message(p, "The " + (mapData.water ? "water" : "lava") + " will &aflood in layers %Sthis round!");
|
||||
if (mapData.fast) Player.Message(p, "The lava will be &cfast %Sthis round!");
|
||||
if (mapData.killer) Player.Message(p, "The " + (mapData.water ? "water" : "lava") + " will &ckill you %Sthis round!");
|
||||
if (mapData.destroy) Player.Message(p, "The " + (mapData.water ? "water" : "lava") + " will &cdestroy plants " + (mapData.water ? "" : "and flammable blocks ") + "%Sthis round!");
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadMap(string name)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name) || !HasMap(name)) return;
|
||||
|
||||
name = name.ToLower();
|
||||
Level oldMap = null;
|
||||
if (active && map != null) oldMap = map;
|
||||
CmdLoad.LoadLevel(null, name);
|
||||
map = LevelInfo.FindExact(name);
|
||||
|
||||
if (map != null)
|
||||
{
|
||||
mapSettings = LoadMapSettings(name);
|
||||
mapData = GenerateMapData(mapSettings);
|
||||
map.SaveChanges = false;
|
||||
|
||||
map.SetPhysics(mapData.destroy ? 2 : 1);
|
||||
map.Config.PhysicsOverload = 1000000;
|
||||
map.Config.AutoUnload = false;
|
||||
map.Config.LoadOnGoto = false;
|
||||
Level.SaveSettings(map);
|
||||
}
|
||||
|
||||
if (active && map != null)
|
||||
{
|
||||
sendingPlayers = true;
|
||||
try
|
||||
{
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in online) {
|
||||
pl.Game.RatedMap = false;
|
||||
pl.Game.PledgeSurvive = false;
|
||||
if (pl.level == oldMap)
|
||||
{
|
||||
if (sendAfkMain && pl.IsAfk)
|
||||
PlayerActions.ChangeMap(pl, Server.mainLevel);
|
||||
else
|
||||
PlayerActions.ChangeMap(pl, map);
|
||||
}
|
||||
}
|
||||
oldMap.Unload(true, false);
|
||||
}
|
||||
catch { }
|
||||
sendingPlayers = false;
|
||||
|
||||
StartRound();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartVote()
|
||||
{
|
||||
if (maps.Count < 3) return;
|
||||
|
||||
// Make sure these are cleared or bad stuff happens!
|
||||
votes.Clear();
|
||||
voted.Clear();
|
||||
|
||||
byte i = 0;
|
||||
string opt, str = "";
|
||||
while (i < Math.Min(voteCount, maps.Count - 1))
|
||||
{
|
||||
opt = maps[rand.Next(maps.Count)];
|
||||
if (!votes.ContainsKey(opt) && opt != map.name)
|
||||
{
|
||||
votes.Add(opt, 0);
|
||||
str += "%S, &5" + opt.Capitalize();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
map.ChatLevel("Vote for the next map! The vote ends in " + voteTime + " minute" + (voteTime == 1 ? "" : "s") +".");
|
||||
map.ChatLevel("Choices: " + str.Remove(0, 4));
|
||||
|
||||
voteTimer = new Timer(TimeSpan.FromMinutes(voteTime).TotalMilliseconds);
|
||||
voteTimer.AutoReset = false;
|
||||
voteTimer.Elapsed += delegate
|
||||
{
|
||||
try {
|
||||
EndVote();
|
||||
voteTimer.Dispose();
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
};
|
||||
voteTimer.Start();
|
||||
voteActive = true;
|
||||
}
|
||||
|
||||
List<string> GetVotedLevels() {
|
||||
var keys = votes.Keys;
|
||||
List<string> names = new List<string>();
|
||||
foreach (string key in keys)
|
||||
names.Add(key);
|
||||
return names;
|
||||
}
|
||||
|
||||
public void EndVote() {
|
||||
if (!voteActive) return;
|
||||
|
||||
voteActive = false;
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Vote ended.");
|
||||
KeyValuePair<string, int> most = new KeyValuePair<string, int>(String.Empty, -1);
|
||||
foreach (KeyValuePair<string, int> kvp in votes)
|
||||
{
|
||||
if (kvp.Value > most.Value) most = kvp;
|
||||
map.ChatLevelOps("&5" + kvp.Key.Capitalize() + "&f: &a" + kvp.Value);
|
||||
}
|
||||
votes.Clear();
|
||||
voted.Clear();
|
||||
|
||||
map.ChatLevel("The vote has ended! &5" + most.Key.Capitalize() + " %Swon with &a" + most.Value + " %Svote" + (most.Value == 1 ? "" : "s") + ".");
|
||||
map.ChatLevel("You will be transferred in 5 seconds...");
|
||||
transferTimer = new Timer(5000);
|
||||
transferTimer.AutoReset = false;
|
||||
transferTimer.Elapsed += delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadMap(most.Key);
|
||||
transferTimer.Dispose();
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
};
|
||||
transferTimer.Start();
|
||||
}
|
||||
|
||||
public bool AddVote(Player p, string vote)
|
||||
{
|
||||
if (!voteActive || voted.Contains(p.name) || !votes.ContainsKey(vote)) return false;
|
||||
int temp = votes[vote] + 1;
|
||||
votes.Remove(vote);
|
||||
votes.Add(vote, temp);
|
||||
voted.Add(p.name);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool HasVote(string vote)
|
||||
{
|
||||
return voteActive && votes.ContainsKey(vote);
|
||||
}
|
||||
|
||||
public bool HasPlayer(Player p)
|
||||
{
|
||||
return p.level == map;
|
||||
}
|
||||
public void KillPlayer(Player p, bool silent = false)
|
||||
{
|
||||
if (lifeNum < 1) return;
|
||||
string name = p.name.ToLower();
|
||||
if (!deaths.ContainsKey(name))
|
||||
deaths.Add(name, 0);
|
||||
deaths[name]++;
|
||||
|
||||
if (!silent && IsPlayerDead(p))
|
||||
{
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in online) {
|
||||
if (pl != p && HasPlayer(pl))
|
||||
Player.Message(pl, p.ColoredName + " &4ran out of lives, and is out of the round!");
|
||||
}
|
||||
Player.Message(p, "&4You ran out of lives, and are out of the round!");
|
||||
Player.Message(p, "&4You can still watch, but you cannot build.");
|
||||
}
|
||||
}
|
||||
public bool IsPlayerDead(Player p)
|
||||
{
|
||||
string name = p.name.ToLower();
|
||||
if (lifeNum < 1 || !deaths.ContainsKey(name))
|
||||
return false;
|
||||
return (deaths[name] >= lifeNum);
|
||||
}
|
||||
|
||||
public void AddMap(string name)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(name) && !HasMap(name))
|
||||
{
|
||||
maps.Add(name.ToLower());
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
public void RemoveMap(string name)
|
||||
{
|
||||
if (maps.CaselessRemove(name))
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
public bool HasMap(string name)
|
||||
{
|
||||
return maps.CaselessContains(name);
|
||||
}
|
||||
|
||||
public bool InSafeZone(Vec3U16 pos)
|
||||
{
|
||||
return InSafeZone(pos.X, pos.Y, pos.Z);
|
||||
}
|
||||
|
||||
public bool InSafeZone(ushort x, ushort y, ushort z)
|
||||
{
|
||||
if (mapSettings == null) return false;
|
||||
return x >= mapSettings.safeZone[0].X && x <= mapSettings.safeZone[1].X && y >= mapSettings.safeZone[0].Y
|
||||
&& y <= mapSettings.safeZone[1].Y && z >= mapSettings.safeZone[0].Z && z <= mapSettings.safeZone[1].Z;
|
||||
}
|
||||
|
||||
public List<string> Maps
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<string>(maps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using MCGalaxy.Maths;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
public sealed partial class LSGame : RoundsGame {
|
||||
|
||||
public void StartRound() {
|
||||
if (roundActive) return;
|
||||
|
||||
try {
|
||||
deaths.Clear();
|
||||
mapData.roundTimer.Elapsed += delegate { EndRound(); };
|
||||
mapData.floodTimer.Elapsed += delegate { DoFlood(); };
|
||||
mapData.roundTimer.Start();
|
||||
mapData.floodTimer.Start();
|
||||
announceTimer.Start();
|
||||
startTime = DateTime.UtcNow;
|
||||
roundActive = true;
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Round started. Map: " + Map.ColoredName);
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
}
|
||||
|
||||
protected override void DoRound() {
|
||||
if (!running) return;
|
||||
}
|
||||
|
||||
// RTound format
|
||||
// announce / round countdown
|
||||
// flood / flood layers
|
||||
// vote for next
|
||||
|
||||
public override void EndRound() {
|
||||
if (!roundActive) return;
|
||||
|
||||
roundActive = false;
|
||||
flooded = false;
|
||||
|
||||
try {
|
||||
try { mapData.Dispose(); }
|
||||
catch { }
|
||||
Map.SetPhysics(5);
|
||||
Map.ChatLevel("The round has ended!");
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Round ended. Voting...");
|
||||
StartVote();
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
}
|
||||
|
||||
public void DoFlood()
|
||||
{
|
||||
if (!running || !roundActive || flooded || Map == null) return;
|
||||
flooded = true;
|
||||
|
||||
try
|
||||
{
|
||||
announceTimer.Stop();
|
||||
Map.ChatLevel("&4Look out, here comes the flood!");
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Map flooding.");
|
||||
if (mapData.layer)
|
||||
{
|
||||
DoFloodLayer();
|
||||
mapData.layerTimer.Elapsed += delegate
|
||||
{
|
||||
if (mapData.currentLayer <= mapSettings.LayerCount)
|
||||
{
|
||||
DoFloodLayer();
|
||||
}
|
||||
else
|
||||
mapData.layerTimer.Stop();
|
||||
};
|
||||
mapData.layerTimer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
Map.Blockchange(mapSettings.FloodPos.X, mapSettings.FloodPos.Y, mapSettings.FloodPos.Z, mapData.block, true);
|
||||
}
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
}
|
||||
|
||||
void DoFloodLayer() {
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Layer " + mapData.currentLayer + " flooding.");
|
||||
Map.Blockchange(mapSettings.LayerPos.X, (ushort)(mapSettings.LayerPos.Y + ((mapSettings.LayerHeight * mapData.currentLayer) - 1)), mapSettings.LayerPos.Z, mapData.block, true);
|
||||
mapData.currentLayer++;
|
||||
}
|
||||
|
||||
public void AnnounceTimeLeft(bool flood, bool round, Player p = null, bool console = false) {
|
||||
if (!running || !roundActive || startTime == null || Map == null) return;
|
||||
|
||||
if (flood) {
|
||||
double floodMinutes = Math.Ceiling((startTime.AddMinutes(mapSettings.floodTime) - DateTime.UtcNow).TotalMinutes);
|
||||
if (p == null && !console) Map.ChatLevel("&3" + floodMinutes + " minute" + (floodMinutes == 1 ? "" : "s") + " %Suntil the flood.");
|
||||
else Player.Message(p, "&3" + floodMinutes + " minute" + (floodMinutes == 1 ? "" : "s") + " %Suntil the flood.");
|
||||
}
|
||||
if (round) {
|
||||
double roundMinutes = Math.Ceiling((startTime.AddMinutes(mapSettings.roundTime) - DateTime.UtcNow).TotalMinutes);
|
||||
if (p == null && !console) Map.ChatLevel("&3" + roundMinutes + " minute" + (roundMinutes == 1 ? "" : "s") + " %Suntil the round ends.");
|
||||
else Player.Message(p, "&3" + roundMinutes + " minute" + (roundMinutes == 1 ? "" : "s") + " %Suntil the round ends.");
|
||||
}
|
||||
}
|
||||
|
||||
public void AnnounceRoundInfo(Player p = null, bool console = false) {
|
||||
if (p == null && !console) {
|
||||
if (mapData.water) Map.ChatLevel("The map will be flooded with &9water %Sthis round!");
|
||||
if (mapData.layer)
|
||||
{
|
||||
Map.ChatLevel("The " + (mapData.water ? "water" : "lava") + " will &aflood in layers %Sthis round!");
|
||||
Map.ChatLevelOps("There will be " + mapSettings.LayerCount + " layers, each " + mapSettings.LayerHeight + " blocks high.");
|
||||
Map.ChatLevelOps("There will be another layer every " + mapSettings.layerInterval + " minutes.");
|
||||
}
|
||||
if (mapData.fast) Map.ChatLevel("The lava will be &cfast %Sthis round!");
|
||||
if (mapData.killer) Map.ChatLevel("The " + (mapData.water ? "water" : "lava") + " will &ckill you %Sthis round!");
|
||||
if (mapData.destroy) Map.ChatLevel("The " + (mapData.water ? "water" : "lava") + " will &cdestroy plants " + (mapData.water ? "" : "and flammable blocks ") + "%Sthis round!");
|
||||
} else {
|
||||
if (mapData.water) Player.Message(p, "The map will be flooded with &9water %Sthis round!");
|
||||
if (mapData.layer) Player.Message(p, "The " + (mapData.water ? "water" : "lava") + " will &aflood in layers %Sthis round!");
|
||||
if (mapData.fast) Player.Message(p, "The lava will be &cfast %Sthis round!");
|
||||
if (mapData.killer) Player.Message(p, "The " + (mapData.water ? "water" : "lava") + " will &ckill you %Sthis round!");
|
||||
if (mapData.destroy) Player.Message(p, "The " + (mapData.water ? "water" : "lava") + " will &cdestroy plants " + (mapData.water ? "" : "and flammable blocks ") + "%Sthis round!");
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadMap(string name)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name) || !HasMap(name)) return;
|
||||
|
||||
name = name.ToLower();
|
||||
Level oldMap = null;
|
||||
if (running && Map != null) oldMap = Map;
|
||||
CmdLoad.LoadLevel(null, name);
|
||||
Map = LevelInfo.FindExact(name);
|
||||
|
||||
if (Map != null) {
|
||||
mapSettings = LoadMapSettings(name);
|
||||
mapData = GenerateMapData(mapSettings);
|
||||
Map.SaveChanges = false;
|
||||
|
||||
Map.SetPhysics(mapData.destroy ? 2 : 1);
|
||||
Map.Config.PhysicsOverload = 1000000;
|
||||
Map.Config.LoadOnGoto = false;
|
||||
Level.SaveSettings(Map);
|
||||
}
|
||||
|
||||
if (running && Map != null)
|
||||
{
|
||||
sendingPlayers = true;
|
||||
try
|
||||
{
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in online) {
|
||||
pl.Game.RatedMap = false;
|
||||
pl.Game.PledgeSurvive = false;
|
||||
if (pl.level == oldMap)
|
||||
{
|
||||
if (sendAfkMain && pl.IsAfk)
|
||||
PlayerActions.ChangeMap(pl, Server.mainLevel);
|
||||
else
|
||||
PlayerActions.ChangeMap(pl, Map);
|
||||
}
|
||||
}
|
||||
oldMap.Unload(true, false);
|
||||
}
|
||||
catch { }
|
||||
sendingPlayers = false;
|
||||
|
||||
StartRound();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartVote()
|
||||
{
|
||||
if (maps.Count < 3) return;
|
||||
|
||||
// Make sure these are cleared or bad stuff happens!
|
||||
votes.Clear();
|
||||
voted.Clear();
|
||||
|
||||
byte i = 0;
|
||||
string opt, str = "";
|
||||
while (i < Math.Min(voteCount, maps.Count - 1))
|
||||
{
|
||||
opt = maps[rand.Next(maps.Count)];
|
||||
if (!votes.ContainsKey(opt) && opt != Map.name)
|
||||
{
|
||||
votes.Add(opt, 0);
|
||||
str += "%S, &5" + opt.Capitalize();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
Map.ChatLevel("Vote for the next map! The vote ends in " + voteTime + " minute" + (voteTime == 1 ? "" : "s") +".");
|
||||
Map.ChatLevel("Choices: " + str.Remove(0, 4));
|
||||
|
||||
voteTimer = new Timer(TimeSpan.FromMinutes(voteTime).TotalMilliseconds);
|
||||
voteTimer.AutoReset = false;
|
||||
voteTimer.Elapsed += delegate
|
||||
{
|
||||
try {
|
||||
EndVote();
|
||||
voteTimer.Dispose();
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
};
|
||||
voteTimer.Start();
|
||||
voteActive = true;
|
||||
}
|
||||
|
||||
public void EndVote() {
|
||||
if (!voteActive) return;
|
||||
|
||||
voteActive = false;
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Vote ended.");
|
||||
KeyValuePair<string, int> most = new KeyValuePair<string, int>(String.Empty, -1);
|
||||
foreach (KeyValuePair<string, int> kvp in votes)
|
||||
{
|
||||
if (kvp.Value > most.Value) most = kvp;
|
||||
Map.ChatLevelOps("&5" + kvp.Key.Capitalize() + "&f: &a" + kvp.Value);
|
||||
}
|
||||
votes.Clear();
|
||||
voted.Clear();
|
||||
|
||||
Map.ChatLevel("The vote has ended! &5" + most.Key.Capitalize() + " %Swon with &a" + most.Value + " %Svote" + (most.Value == 1 ? "" : "s") + ".");
|
||||
Map.ChatLevel("You will be transferred in 5 seconds...");
|
||||
transferTimer = new Timer(5000);
|
||||
transferTimer.AutoReset = false;
|
||||
transferTimer.Elapsed += delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
LoadMap(most.Key);
|
||||
transferTimer.Dispose();
|
||||
}
|
||||
catch (Exception e) { Logger.LogError(e); }
|
||||
};
|
||||
transferTimer.Start();
|
||||
}
|
||||
|
||||
public bool AddVote(Player p, string vote) {
|
||||
if (!voteActive || voted.Contains(p.name) || !votes.ContainsKey(vote)) return false;
|
||||
int temp = votes[vote] + 1;
|
||||
votes.Remove(vote);
|
||||
votes.Add(vote, temp);
|
||||
voted.Add(p.name);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool HasVote(string vote) {
|
||||
return voteActive && votes.ContainsKey(vote);
|
||||
}
|
||||
|
||||
void KillPlayer(Player p) {
|
||||
if (lifeNum < 1) return;
|
||||
string name = p.name.ToLower();
|
||||
if (!deaths.ContainsKey(name)) deaths.Add(name, 0);
|
||||
deaths[name]++;
|
||||
if (!IsPlayerDead(p)) return;
|
||||
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in online) {
|
||||
if (pl != p && pl.level == Map) {
|
||||
Player.Message(pl, p.ColoredName + " &4ran out of lives, and is out of the round!");
|
||||
}
|
||||
}
|
||||
|
||||
Player.Message(p, "&4You ran out of lives, and are out of the round!");
|
||||
Player.Message(p, "&4You can still watch, but you cannot build.");
|
||||
}
|
||||
}
|
||||
}
|
165
MCGalaxy/Games/LavaSurvival/LSGame.cs
Normal file
165
MCGalaxy/Games/LavaSurvival/LSGame.cs
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
using MCGalaxy.Commands.World;
|
||||
using MCGalaxy.Maths;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
public sealed partial class LSGame : RoundsGame {
|
||||
// Private variables
|
||||
const string propsDir = "properties/lavasurvival/";
|
||||
List<string> maps, voted;
|
||||
Dictionary<string, int> votes, deaths;
|
||||
Random rand = new Random();
|
||||
Timer announceTimer, voteTimer, transferTimer;
|
||||
DateTime startTime;
|
||||
|
||||
// Public variables
|
||||
public bool running = false, roundActive = false, flooded = false, voteActive = false, sendingPlayers = false;
|
||||
public MapSettings mapSettings;
|
||||
public MapData mapData;
|
||||
|
||||
public override string GameName { get { return "Lava survival"; } }
|
||||
public override bool Running { get { return running; } }
|
||||
|
||||
// Settings
|
||||
public bool startOnStartup, sendAfkMain = true;
|
||||
public byte voteCount = 2;
|
||||
public int lifeNum = 3;
|
||||
public double voteTime = 2;
|
||||
|
||||
// Constructors
|
||||
public LSGame() {
|
||||
maps = new List<string>();
|
||||
voted = new List<string>();
|
||||
votes = new Dictionary<string, int>();
|
||||
deaths = new Dictionary<string, int>();
|
||||
announceTimer = new Timer(60000);
|
||||
announceTimer.AutoReset = true;
|
||||
announceTimer.Elapsed += delegate
|
||||
{
|
||||
if (!flooded) AnnounceTimeLeft(true, false);
|
||||
};
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
// Public methods
|
||||
public byte Start(string mapName = "")
|
||||
{
|
||||
if (running) return 1; // Already started
|
||||
if (maps.Count < 3) return 2; // Not enough maps
|
||||
if (!String.IsNullOrEmpty(mapName) && !HasMap(mapName)) return 3; // Map doesn't exist
|
||||
|
||||
deaths.Clear();
|
||||
running = true;
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Game started.");
|
||||
|
||||
try {
|
||||
LoadMap(String.IsNullOrEmpty(mapName) ? maps[rand.Next(maps.Count)] : mapName);
|
||||
HookEventHandlers();
|
||||
} catch (Exception e) {
|
||||
Logger.LogError(e); running = false; return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void End() {
|
||||
if (!running) return;
|
||||
UnhookEventHandlers();
|
||||
|
||||
running = false;
|
||||
roundActive = false;
|
||||
voteActive = false;
|
||||
flooded = false;
|
||||
deaths.Clear();
|
||||
if (announceTimer.Enabled) announceTimer.Stop();
|
||||
try { mapData.Dispose(); }
|
||||
catch { }
|
||||
try { voteTimer.Dispose(); }
|
||||
catch { }
|
||||
try { transferTimer.Dispose(); }
|
||||
catch { }
|
||||
Map.Unload(true, false);
|
||||
Map = null;
|
||||
Logger.Log(LogType.GameActivity, "[Lava Survival] Game stopped.");
|
||||
}
|
||||
|
||||
public bool IsPlayerDead(Player p) {
|
||||
string name = p.name.ToLower();
|
||||
if (lifeNum < 1 || !deaths.ContainsKey(name))
|
||||
return false;
|
||||
return (deaths[name] >= lifeNum);
|
||||
}
|
||||
|
||||
public void AddMap(string name) {
|
||||
if (!String.IsNullOrEmpty(name) && !HasMap(name)) {
|
||||
maps.Add(name.ToLower());
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveMap(string name) {
|
||||
if (maps.CaselessRemove(name)) {
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasMap(string name) {
|
||||
return maps.CaselessContains(name);
|
||||
}
|
||||
|
||||
public bool InSafeZone(ushort x, ushort y, ushort z) {
|
||||
if (mapSettings == null) return false;
|
||||
return x >= mapSettings.safeZone[0].X && x <= mapSettings.safeZone[1].X && y >= mapSettings.safeZone[0].Y
|
||||
&& y <= mapSettings.safeZone[1].Y && z >= mapSettings.safeZone[0].Z && z <= mapSettings.safeZone[1].Z;
|
||||
}
|
||||
|
||||
public List<string> Maps { get { return new List<string>(maps); } }
|
||||
|
||||
|
||||
public override bool HandlesChatMessage(Player p, string message) {
|
||||
if (!running || p.level != Map) return false;
|
||||
message = message.ToLower();
|
||||
if (!HasVote(message)) return false;
|
||||
|
||||
if (AddVote(p, message)) {
|
||||
Player.Message(p, "Your vote for &5" + message.Capitalize() + " %Shas been placed. Thanks!");
|
||||
Map.ChatLevelOps(p.name + " voted for &5" + message.Capitalize() + "%S.");
|
||||
return true;
|
||||
} else {
|
||||
Player.Message(p, "&cYou already voted!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void PlayerJoinedLevel(Player p, Level lvl, Level oldLevl) {
|
||||
if (running && !sendingPlayers && Map == lvl) {
|
||||
if (roundActive) {
|
||||
AnnounceRoundInfo(p);
|
||||
AnnounceTimeLeft(!flooded, true, p);
|
||||
} else {
|
||||
Player.Message(p, "Vote for the next map!");
|
||||
Player.Message(p, "Choices: &5" + votes.Keys.Join("%S, &5"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
Copyright 2011 MCForge
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
public sealed partial class LavaSurvival : IGame {
|
||||
|
||||
public override bool HandlesChatMessage(Player p, string message) {
|
||||
if (!HasPlayer(p)) return false;
|
||||
message = message.ToLower();
|
||||
if (!HasVote(message)) return false;
|
||||
|
||||
if (AddVote(p, message)) {
|
||||
Player.Message(p, "Your vote for &5" + message.Capitalize() + " %Shas been placed. Thanks!");
|
||||
return true;
|
||||
} else {
|
||||
Player.Message(p, "&cYou already voted!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void PlayerJoinedServer(Player p) {
|
||||
if (!active) return;
|
||||
Player.Message(p, "There is a &aLava Survival %Sgame active! Join it by typing /ls go");
|
||||
}
|
||||
|
||||
public override void PlayerJoinedLevel(Player p, Level lvl, Level oldLevl) {
|
||||
if (active && !sendingPlayers && map == lvl) {
|
||||
if (roundActive) {
|
||||
AnnounceRoundInfo(p);
|
||||
AnnounceTimeLeft(!flooded, true, p);
|
||||
} else {
|
||||
Player.Message(p, "Vote for the next map!");
|
||||
Player.Message(p, "Choices: &5" + votes.Keys.Join("%S, &5"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,7 +24,9 @@ namespace MCGalaxy.Games {
|
||||
public abstract class LevelPicker {
|
||||
public string QueuedMap;
|
||||
public List<string> RecentMaps = new List<string>();
|
||||
|
||||
public int VoteTime = 20;
|
||||
public bool Voting;
|
||||
|
||||
internal string Candidate1 = "", Candidate2 = "", Candidate3 = "";
|
||||
internal int Votes1 = 0, Votes2 = 0, Votes3 = 0;
|
||||
|
||||
@ -43,16 +45,16 @@ namespace MCGalaxy.Games {
|
||||
if (QueuedMap != null) return QueuedMap;
|
||||
|
||||
try {
|
||||
List<string> maps = GetCandidateLevels();
|
||||
List<string> maps = GetCandidateMaps();
|
||||
if (maps == null) return null;
|
||||
|
||||
RemoveRecentLevels(maps);
|
||||
Votes1 = 0; Votes2 = 0; Votes3 = 0;
|
||||
|
||||
Random r = new Random();
|
||||
Candidate1 = GetRandomLevel(r, maps);
|
||||
Candidate2 = GetRandomLevel(r, maps);
|
||||
Candidate3 = GetRandomLevel(r, maps);
|
||||
Candidate1 = GetRandomMap(r, maps);
|
||||
Candidate2 = GetRandomMap(r, maps);
|
||||
Candidate3 = GetRandomMap(r, maps);
|
||||
|
||||
if (!game.Running) return null;
|
||||
DoLevelVote(game);
|
||||
@ -80,7 +82,7 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
void DoLevelVote(IGame game) {
|
||||
Server.votingforlevel = true;
|
||||
Voting = true;
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in players) {
|
||||
if (pl.level != game.Map) continue;
|
||||
@ -88,7 +90,7 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
VoteCountdown(game);
|
||||
Server.votingforlevel = false;
|
||||
Voting = false;
|
||||
}
|
||||
|
||||
void VoteCountdown(IGame game) {
|
||||
@ -96,16 +98,17 @@ namespace MCGalaxy.Games {
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in players) {
|
||||
if (pl.level != game.Map || pl.Supports(CpeExt.MessageTypes)) continue;
|
||||
pl.SendMessage("You have 20 seconds to vote for the next map");
|
||||
pl.SendMessage("You have " + VoteTime + " seconds to vote for the next map");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
for (int i = 0; i < VoteTime; i++) {
|
||||
players = PlayerInfo.Online.Items;
|
||||
if (!game.Running) return;
|
||||
|
||||
foreach (Player pl in players) {
|
||||
if (pl.level != game.Map || !pl.Supports(CpeExt.MessageTypes)) continue;
|
||||
pl.SendCpeMessage(CpeMessageType.BottomRight1, "&e" + (20 - i) + "s %Sleft to vote");
|
||||
string timeLeft = "&e" + (VoteTime - i) + "s %Sleft to vote";
|
||||
pl.SendCpeMessage(CpeMessageType.BottomRight1, timeLeft);
|
||||
}
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
@ -115,33 +118,25 @@ namespace MCGalaxy.Games {
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in online) pl.voted = false;
|
||||
|
||||
if (Votes1 >= Votes2) {
|
||||
if (Votes3 > Votes1 && Votes3 > Votes2) {
|
||||
return Candidate3;
|
||||
} else {
|
||||
return Candidate1;
|
||||
}
|
||||
if (Votes3 > Votes1 && Votes3 > Votes2) {
|
||||
return Candidate3;
|
||||
} else if (Votes1 >= Votes2) {
|
||||
return Candidate1;
|
||||
} else {
|
||||
if (Votes3 > Votes1 && Votes3 > Votes2) {
|
||||
return Candidate3;
|
||||
} else {
|
||||
return Candidate2;
|
||||
}
|
||||
return Candidate2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal static string GetRandomLevel(Random r, List<string> maps) {
|
||||
internal static string GetRandomMap(Random r, List<string> maps) {
|
||||
int i = r.Next(0, maps.Count);
|
||||
string map = maps[i];
|
||||
|
||||
string map = maps[i];
|
||||
maps.RemoveAt(i);
|
||||
return map;
|
||||
}
|
||||
|
||||
/// <summary> Returns a list of maps that can be used for a round of this game. </summary>
|
||||
/// <returns> null if not enough levels are available, otherwise the list of levels. </returns>
|
||||
public abstract List<string> GetCandidateLevels();
|
||||
public abstract List<string> GetCandidateMaps();
|
||||
|
||||
/// <summary> Sends the formatted vote message to the player (using bottom right if supported) </summary>
|
||||
public void SendVoteMessage(Player p) {
|
||||
@ -156,5 +151,15 @@ namespace MCGalaxy.Games {
|
||||
Player.Message(p, line2);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HandlesMessage(Player p, string message) {
|
||||
if (!Voting) return false;
|
||||
message = message.ToLower();
|
||||
|
||||
return
|
||||
Player.CheckVote(message, p, "1", "one", ref Votes1) ||
|
||||
Player.CheckVote(message, p, "2", "two", ref Votes2) ||
|
||||
Player.CheckVote(message, p, "3", "three", ref Votes3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ namespace MCGalaxy.Games.ZS {
|
||||
internal static void UpdateAllPrimary(ZSGame game) {
|
||||
int left = (int)(game.RoundEnd - DateTime.UtcNow).TotalSeconds;
|
||||
string status = FormatPrimary(game, left);
|
||||
MessageAll(game, CpeMessageType.Status1, status);
|
||||
game.MessageMap(CpeMessageType.Status1, status);
|
||||
}
|
||||
|
||||
internal static void UpdatePrimary(ZSGame game, Player p) {
|
||||
@ -34,7 +34,7 @@ namespace MCGalaxy.Games.ZS {
|
||||
|
||||
internal static void UpdateAllSecondary(ZSGame game) {
|
||||
string status = FormatSecondary(game);
|
||||
MessageAll(game, CpeMessageType.Status2, status);
|
||||
game.MessageMap(CpeMessageType.Status2, status);
|
||||
}
|
||||
|
||||
internal static void UpdateSecondary(ZSGame game, Player p) {
|
||||
@ -70,10 +70,10 @@ namespace MCGalaxy.Games.ZS {
|
||||
string timespan = GetTimeLeft(seconds);
|
||||
if (timespan.Length > 0) {
|
||||
const string format = "&a{0} %Salive %S({2}, map: {1})";
|
||||
return String.Format(format, game.Alive.Count, game.MapName, timespan);
|
||||
return String.Format(format, game.Alive.Count, game.Map.MapName, timespan);
|
||||
} else {
|
||||
const string format = "&a{0} %Salive %S(map: {1})";
|
||||
return String.Format(format, game.Alive.Count, game.MapName);
|
||||
return String.Format(format, game.Alive.Count, game.Map.MapName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,14 +88,5 @@ namespace MCGalaxy.Games.ZS {
|
||||
string state = ", you are " + (p.Game.Infected ? "&cdead" : "&aalive");
|
||||
return money + state;
|
||||
}
|
||||
|
||||
static void MessageAll(ZSGame game, CpeMessageType type, string message) {
|
||||
if (!game.Running) return;
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player p in online) {
|
||||
if (!p.level.name.CaselessEq(game.MapName)) continue;
|
||||
p.SendCpeMessage(type, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
Copyright 2010 MCLawl Team -
|
||||
Created by Snowl (David D.) and Cazzar (Cayde D.)
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.osedu.org/licenses/ECL-2.0
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace MCGalaxy.Games.ZS {
|
||||
internal class ZSLevelPicker : LevelPicker {
|
||||
|
||||
public override List<string> GetCandidateLevels() {
|
||||
List<string> maps = null;
|
||||
if (ZSConfig.LevelList.Count > 0) {
|
||||
maps = new List<string>(ZSConfig.LevelList);
|
||||
} else {
|
||||
maps = AllMaps();
|
||||
}
|
||||
|
||||
foreach (string ignore in ZSConfig.IgnoredLevelList)
|
||||
maps.Remove(ignore);
|
||||
|
||||
bool useLevelList = ZSConfig.LevelList.Count > 0;
|
||||
if (ZSConfig.ChangeLevels && maps.Count <= 3) {
|
||||
string group = useLevelList ? "in your level list " : "";
|
||||
Logger.Log(LogType.Warning, "You must have more than 3 levels {0}to change levels in Zombie Survival", group);
|
||||
return null;
|
||||
} else if (!ZSConfig.ChangeLevels && maps.Count == 0) {
|
||||
string group = useLevelList ? "in your level list " : "";
|
||||
Logger.Log(LogType.Warning, "You must have at least 1 level {0}to play Zombie Survival", group);
|
||||
return null;
|
||||
}
|
||||
return maps;
|
||||
}
|
||||
|
||||
static List<string> AllMaps() {
|
||||
string[] files = LevelInfo.AllMapFiles();
|
||||
List<string> maps = new List<string>(files.Length);
|
||||
|
||||
foreach (string file in files) {
|
||||
string map = Path.GetFileNameWithoutExtension(file);
|
||||
maps.Add(map);
|
||||
}
|
||||
return maps;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
/*
|
||||
Copyright 2010 MCLawl Team -
|
||||
Created by Snowl (David D.) and Cazzar (Cayde D.)
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.osedu.org/licenses/ECL-2.0
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MCGalaxy.Games.ZS {
|
||||
|
||||
internal static class Rewards {
|
||||
|
||||
public static void HandOut(ZSGame game) {
|
||||
Player[] alive = game.Alive.Items, dead = game.Infected.Items;
|
||||
game.Map.ChatLevel("&aThe game has ended!");
|
||||
|
||||
if (alive.Length == 0) game.Map.ChatLevel("&4Zombies have won this round.");
|
||||
else if (alive.Length == 1) game.Map.ChatLevel("&2Congratulations to the sole survivor:");
|
||||
else game.Map.ChatLevel("&2Congratulations to the survivors:");
|
||||
AnnounceWinners(game, alive, dead);
|
||||
|
||||
game.Map.Config.RoundsPlayed++;
|
||||
if (alive.Length > 0) {
|
||||
game.Map.Config.RoundsHumanWon++;
|
||||
foreach (Player p in alive)
|
||||
IncreaseAliveStats(p, game);
|
||||
}
|
||||
|
||||
GiveMoney(game, alive);
|
||||
}
|
||||
|
||||
static void AnnounceWinners(ZSGame game, Player[] alive, Player[] dead) {
|
||||
if (alive.Length > 0) {
|
||||
string winners = alive.Join(p => p.ColoredName);
|
||||
game.Map.ChatLevel(winners);
|
||||
return;
|
||||
}
|
||||
|
||||
int maxKills = 0, count = 0;
|
||||
for (int i = 0; i < dead.Length; i++) {
|
||||
maxKills = Math.Max(maxKills, dead[i].Game.CurrentInfected);
|
||||
}
|
||||
for (int i = 0; i < dead.Length; i++) {
|
||||
if (dead[i].Game.CurrentInfected == maxKills) count++;
|
||||
}
|
||||
|
||||
string group = count == 1 ? " zombie " : " zombies ";
|
||||
string suffix = maxKills == 1 ? " %Skill" : " %Skills";
|
||||
StringFormatter<Player> formatter = p => p.Game.CurrentInfected == maxKills ? p.ColoredName : null;
|
||||
|
||||
game.Map.ChatLevel("&8Best" + group + "%S(&b" + maxKills
|
||||
+ suffix + "%S)&8: " + dead.Join(formatter));
|
||||
}
|
||||
|
||||
static void IncreaseAliveStats(Player p, ZSGame game) {
|
||||
if (p.Game.PledgeSurvive) {
|
||||
Player.Message(p, "You received &a5 %3" + ServerConfig.Currency +
|
||||
" %Sfor successfully pledging that you would survive.");
|
||||
p.SetMoney(p.money + 5);
|
||||
}
|
||||
|
||||
p.Game.CurrentRoundsSurvived++;
|
||||
p.Game.TotalRoundsSurvived++;
|
||||
p.Game.MaxRoundsSurvived = Math.Max(p.Game.CurrentRoundsSurvived, p.Game.MaxRoundsSurvived);
|
||||
p.SetPrefix(); // stars before name
|
||||
}
|
||||
|
||||
static void GiveMoney(ZSGame game, Player[] alive) {
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
Random rand = new Random();
|
||||
|
||||
foreach (Player pl in online) {
|
||||
if (!pl.level.name.CaselessEq(game.MapName)) continue;
|
||||
pl.Game.ResetInvisibility();
|
||||
int reward = GetMoneyReward(pl, alive, rand);
|
||||
|
||||
if (reward == -1) {
|
||||
pl.SendMessage("You may not hide inside a block! No " + ServerConfig.Currency + " for you."); reward = 0;
|
||||
} else if (reward > 0) {
|
||||
pl.SendMessage(Colors.gold + "You gained " + reward + " " + ServerConfig.Currency);
|
||||
}
|
||||
|
||||
pl.SetMoney(pl.money + reward);
|
||||
pl.Game.ResetZombieState();
|
||||
if (pl.Game.Referee) {
|
||||
pl.SendMessage("You gained one " + ServerConfig.Currency + " because you're a ref. Would you like a medal as well?");
|
||||
pl.SetMoney(pl.money + 1);
|
||||
}
|
||||
|
||||
Entities.GlobalRespawn(pl, false);
|
||||
TabList.Add(pl, pl, Entities.SelfID);
|
||||
HUD.UpdateTertiary(pl);
|
||||
}
|
||||
}
|
||||
|
||||
static int GetMoneyReward(Player pl, Player[] alive, Random rand) {
|
||||
if (pl.CheckIfInsideBlock()) return -1;
|
||||
|
||||
if (alive.Length == 0) {
|
||||
return rand.Next(1 + pl.Game.CurrentInfected, 5 + pl.Game.CurrentInfected);
|
||||
} else if (alive.Length == 1 && !pl.Game.Infected) {
|
||||
return rand.Next(5, 10);
|
||||
} else if (alive.Length > 1 && !pl.Game.Infected) {
|
||||
return rand.Next(2, 6);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -61,8 +61,6 @@ namespace MCGalaxy.Games {
|
||||
public static int ZombieInvisibilityDuration = 5;
|
||||
[ConfigInt("zombie-zinvisibility-potions", "Zombie", 4, 1)]
|
||||
public static int ZombieInvisibilityPotions = 4;
|
||||
[ConfigBool("enable-changing-levels", "Zombie", true)]
|
||||
public static bool ChangeLevels = true;
|
||||
|
||||
[ConfigString("revive-notime-msg", "Revive",
|
||||
"It's too late. The humans do not have enough time left to make more revive potions.")]
|
||||
|
@ -21,45 +21,48 @@ using MCGalaxy.Events.EconomyEvents;
|
||||
using MCGalaxy.Events.EntityEvents;
|
||||
using MCGalaxy.Events.LevelEvents;
|
||||
using MCGalaxy.Events.PlayerEvents;
|
||||
using MCGalaxy.Events.ServerEvents;
|
||||
using MCGalaxy.Games.ZS;
|
||||
using MCGalaxy.Network;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games.ZS {
|
||||
public sealed class ZSPlugin : Plugin_Simple {
|
||||
public override string creator { get { return Server.SoftwareName + " team"; } }
|
||||
public override string MCGalaxy_Version { get { return Server.VersionString; } }
|
||||
public override string name { get { return "Core_ZSPlugin"; } }
|
||||
public ZSGame Game;
|
||||
namespace MCGalaxy.Games {
|
||||
public sealed partial class ZSGame : RoundsGame {
|
||||
|
||||
public override void Load(bool startup) {
|
||||
void HookEventHandlers() {
|
||||
OnEntitySpawnedEvent.Register(HandleEntitySpawned, Priority.High);
|
||||
OnTabListEntryAddedEvent.Register(HandleTabListEntryAdded, Priority.High);
|
||||
OnMoneyChangedEvent.Register(HandleMoneyChanged, Priority.High);
|
||||
OnBlockChangeEvent.Register(HandleBlockChange, Priority.High);
|
||||
OnLevelUnloadEvent.Register(HandleLevelUnload, Priority.High);
|
||||
OnSendingHeartbeatEvent.Register(HandleSendingHeartbeat, Priority.High);
|
||||
|
||||
OnPlayerConnectEvent.Register(HandlePlayerConnect, Priority.High);
|
||||
OnPlayerDisconnectEvent.Register(HandlePlayerDisconnect, Priority.High);
|
||||
OnPlayerMoveEvent.Register(HandlePlayerMove, Priority.High);
|
||||
OnPlayerActionEvent.Register(HandlePlayerAction, Priority.High);
|
||||
OnPlayerSpawningEvent.Register(HandlePlayerSpawning, Priority.High);
|
||||
OnBlockChangeEvent.Register(HandleBlockChange, Priority.High);
|
||||
OnLevelUnloadEvent.Register(HandleLevelUnload, Priority.High);
|
||||
}
|
||||
|
||||
public override void Unload(bool shutdown) {
|
||||
void UnhookEventHandlers() {
|
||||
OnEntitySpawnedEvent.Unregister(HandleEntitySpawned);
|
||||
OnTabListEntryAddedEvent.Unregister(HandleTabListEntryAdded);
|
||||
OnMoneyChangedEvent.Unregister(HandleMoneyChanged);
|
||||
OnBlockChangeEvent.Unregister(HandleBlockChange);
|
||||
OnLevelUnloadEvent.Unregister(HandleLevelUnload);
|
||||
OnSendingHeartbeatEvent.Unregister(HandleSendingHeartbeat);
|
||||
|
||||
OnPlayerConnectEvent.Unregister(HandlePlayerConnect);
|
||||
OnPlayerDisconnectEvent.Unregister(HandlePlayerDisconnect);
|
||||
OnPlayerMoveEvent.Unregister(HandlePlayerMove);
|
||||
OnPlayerActionEvent.Unregister(HandlePlayerAction);
|
||||
OnPlayerSpawningEvent.Unregister(HandlePlayerSpawning);
|
||||
OnBlockChangeEvent.Unregister(HandleBlockChange);
|
||||
OnLevelUnloadEvent.Unregister(HandleLevelUnload);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void HandleTabListEntryAdded(Entity entity, ref string tabName, ref string tabGroup, Player dst) {
|
||||
Player p = entity as Player;
|
||||
if (p == null || p.level != Game.Map) return;
|
||||
if (p == null || p.level != Map) return;
|
||||
|
||||
if (p.Game.Referee) {
|
||||
tabGroup = "&2Referees";
|
||||
@ -76,7 +79,7 @@ namespace MCGalaxy.Games.ZS {
|
||||
}
|
||||
|
||||
void HandleMoneyChanged(Player p) {
|
||||
if (p.level != Game.Map) return;
|
||||
if (p.level != Map) return;
|
||||
HUD.UpdateTertiary(p);
|
||||
}
|
||||
|
||||
@ -93,16 +96,16 @@ namespace MCGalaxy.Games.ZS {
|
||||
}
|
||||
|
||||
void HandlePlayerConnect(Player p) {
|
||||
if (!ZSConfig.SetMainLevel) return;
|
||||
Player.Message(p, "Zombie Survival is running! Type %T/ZS go %Sto join.");
|
||||
if (ZSConfig.SetMainLevel) return;
|
||||
Player.Message(p, "&3Zombie Survival %Sis running! Type %T/ZS go %Sto join");
|
||||
}
|
||||
|
||||
void HandlePlayerDisconnect(Player p, string reason) {
|
||||
Game.PlayerLeftGame(p);
|
||||
PlayerLeftGame(p);
|
||||
}
|
||||
|
||||
void HandlePlayerMove(Player p, Position next, byte rotX, byte rotY) {
|
||||
if (!Game.RoundInProgress || p.level != Game.Map) return;
|
||||
if (!RoundInProgress || p.level != Map) return;
|
||||
|
||||
bool reverted = MovementCheck.DetectNoclip(p, next)
|
||||
|| MovementCheck.DetectSpeedhack(p, next, ZSConfig.MaxMoveDistance);
|
||||
@ -111,10 +114,10 @@ namespace MCGalaxy.Games.ZS {
|
||||
|
||||
void HandlePlayerAction(Player p, PlayerAction action, string message, bool stealth) {
|
||||
if (!(action == PlayerAction.Referee || action == PlayerAction.UnReferee)) return;
|
||||
if (p.level != Game.Map) return;
|
||||
if (p.level != Map) return;
|
||||
|
||||
if (action == PlayerAction.UnReferee) {
|
||||
Game.PlayerJoinedLevel(p, Game.Map, Game.Map);
|
||||
PlayerJoinedLevel(p, Map, Map);
|
||||
Command.all.FindByName("Spawn").Use(p, "");
|
||||
p.Game.Referee = false;
|
||||
|
||||
@ -137,25 +140,24 @@ namespace MCGalaxy.Games.ZS {
|
||||
}
|
||||
|
||||
void HandlePlayerSpawning(Player p, ref Position pos, ref byte yaw, ref byte pitch, bool respawning) {
|
||||
if (p.level != Game.Map) return;
|
||||
|
||||
if (!p.Game.Referee && !p.Game.Infected && Game.RoundInProgress) {
|
||||
Game.InfectPlayer(p, null);
|
||||
if (p.level != Map) return;
|
||||
if (!p.Game.Referee && !p.Game.Infected && RoundInProgress) {
|
||||
InfectPlayer(p, null);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleBlockChange(Player p, ushort x, ushort y, ushort z, BlockID block, bool placing) {
|
||||
if (p.level != Game.Map) return;
|
||||
BlockID old = Game.Map.GetBlock(x, y, z);
|
||||
if (p.level != Map) return;
|
||||
BlockID old = Map.GetBlock(x, y, z);
|
||||
|
||||
if (Game.Map.Config.BuildType == BuildType.NoModify) {
|
||||
if (Map.Config.BuildType == BuildType.NoModify) {
|
||||
p.RevertBlock(x, y, z); p.cancelBlock = true; return;
|
||||
}
|
||||
if (Game.Map.Config.BuildType == BuildType.ModifyOnly && Game.Map.Props[old].OPBlock) {
|
||||
if (Map.Config.BuildType == BuildType.ModifyOnly && Map.Props[old].OPBlock) {
|
||||
p.RevertBlock(x, y, z); p.cancelBlock = true; return;
|
||||
}
|
||||
|
||||
if (Pillaring.Handles(p, x, y, z, placing, block, old, Game)) {
|
||||
if (Pillaring.Handles(p, x, y, z, placing, block, old, this)) {
|
||||
p.cancelBlock = true; return;
|
||||
}
|
||||
|
||||
@ -167,13 +169,19 @@ namespace MCGalaxy.Games.ZS {
|
||||
}
|
||||
|
||||
p.Game.BlocksLeft--;
|
||||
if ((p.Game.BlocksLeft % 10) == 0 || (p.Game.BlocksLeft >= 0 && p.Game.BlocksLeft <= 10))
|
||||
if ((p.Game.BlocksLeft % 10) == 0 || (p.Game.BlocksLeft >= 0 && p.Game.BlocksLeft <= 10)) {
|
||||
Player.Message(p, "Blocks Left: &4" + p.Game.BlocksLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleLevelUnload(Level lvl) {
|
||||
if (lvl == Game.Map) lvl.cancelunload = true;
|
||||
if (lvl == Map) lvl.cancelunload = true;
|
||||
}
|
||||
|
||||
void HandleSendingHeartbeat(Heartbeat service, ref string name) {
|
||||
if (!ZSConfig.IncludeMapInHeartbeat || Map == null) return;
|
||||
name += " (map: " + Map.MapName + ")";
|
||||
}
|
||||
}
|
||||
}
|
@ -18,22 +18,39 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using MCGalaxy.Commands.World;
|
||||
using MCGalaxy.Games.ZS;
|
||||
using MCGalaxy.Network;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
public sealed partial class ZSGame : RoundsGame {
|
||||
public override string GameName { get { return "Zombie survival"; } }
|
||||
|
||||
public sealed partial class ZSGame : RoundsGame {
|
||||
string lastKiller = "";
|
||||
int infectCombo = 0;
|
||||
|
||||
protected override void DoRound() {
|
||||
if (!Running) return;
|
||||
List<Player> players = DoRoundCountdown();
|
||||
if (players == null) return;
|
||||
Random random = new Random();
|
||||
|
||||
RoundInProgress = true;
|
||||
StartRound(players);
|
||||
if (!running) return;
|
||||
|
||||
if (!running) return;
|
||||
EndRound();
|
||||
Picker.AddRecentMap(Map.MapName);
|
||||
|
||||
if (RoundsLeft > 0) {
|
||||
string map = Picker.ChooseNextLevel(this);
|
||||
if (map != null) ChangeLevel(map);
|
||||
}
|
||||
}
|
||||
|
||||
void StartRound(List<Player> players) {
|
||||
Random random = new Random();
|
||||
int roundMins = random.Next(Map.Config.MinRoundTime, Map.Config.MaxRoundTime);
|
||||
string suffix = roundMins == 1 ? " %Sminute!" : " %Sminutes!";
|
||||
Map.ChatLevel("This round will last for &a" + roundMins + suffix);
|
||||
@ -46,64 +63,72 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
Infected.Clear();
|
||||
|
||||
Player first = PickFirstZombie(random, players);
|
||||
Map.ChatLevel("&c" + first.DisplayName + " %Sstarted the infection!");
|
||||
InfectPlayer(first, null);
|
||||
|
||||
DoCoreGame(random);
|
||||
if (!Running) return;
|
||||
EndRound();
|
||||
Picker.AddRecentMap(MapName);
|
||||
|
||||
if (RoundsLeft > 0 && ZSConfig.ChangeLevels) {
|
||||
string map = Picker.ChooseNextLevel(this);
|
||||
if (map != null) ChangeLevel(map);
|
||||
}
|
||||
}
|
||||
|
||||
Player PickFirstZombie(Random random, List<Player> players) {
|
||||
Player first = null;
|
||||
do {
|
||||
first = QueuedZombie != null ?
|
||||
PlayerInfo.FindExact(QueuedZombie) : players[random.Next(players.Count)];
|
||||
first = QueuedZombie != null ? PlayerInfo.FindExact(QueuedZombie) : players[random.Next(players.Count)];
|
||||
QueuedZombie = null;
|
||||
} while (first == null || !first.level.name.CaselessEq(MapName));
|
||||
return first;
|
||||
} while (first == null || first.level != Map);
|
||||
|
||||
Map.ChatLevel("&c" + first.DisplayName + " %Sstarted the infection!");
|
||||
InfectPlayer(first, null);
|
||||
}
|
||||
|
||||
/// <summary> If there are no infected players left, randomly selected one of the alive players to continue the infection. </summary>
|
||||
void AssignFirstZombie() {
|
||||
if (!running || !RoundInProgress || Infected.Count > 0) return;
|
||||
Random random = new Random();
|
||||
Player[] alive = Alive.Items;
|
||||
if (alive.Length == 0) return;
|
||||
int index = random.Next(alive.Length);
|
||||
|
||||
while (alive[index].Game.Referee || alive[index].level != Map) {
|
||||
if (index >= alive.Length - 1) {
|
||||
index = 0;
|
||||
alive = Alive.Items;
|
||||
if (alive.Length == 0) return;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
Player zombie = alive[index];
|
||||
Map.ChatLevel("&c" + zombie.DisplayName + " %Scontinued the infection!");
|
||||
InfectPlayer(zombie, null);
|
||||
}
|
||||
|
||||
List<Player> DoRoundCountdown() {
|
||||
while (true) {
|
||||
RoundStart = DateTime.UtcNow.AddSeconds(30);
|
||||
if (!Running) return null;
|
||||
if (!running) return null;
|
||||
|
||||
SendLevelRaw("&4Starting in &f30 &4seconds", true);
|
||||
Thread.Sleep(10000); if (!Running) return null;
|
||||
Thread.Sleep(10000); if (!running) return null;
|
||||
SendLevelRaw("&4Starting in &f20 &4seconds", true);
|
||||
Thread.Sleep(10000); if (!Running) return null;
|
||||
Thread.Sleep(10000); if (!running) return null;
|
||||
SendLevelRaw("&4Starting in &f10 &4seconds", true);
|
||||
Thread.Sleep(5000); if (!Running) return null;
|
||||
Thread.Sleep(5000); if (!running) return null;
|
||||
SendLevelRaw("&4Starting in &f5 &4seconds", true);
|
||||
Thread.Sleep(1000); if (!Running) return null;
|
||||
Thread.Sleep(1000); if (!running) return null;
|
||||
SendLevelRaw("&4Starting in &f4 &4seconds", true);
|
||||
Thread.Sleep(1000); if (!Running) return null;
|
||||
Thread.Sleep(1000); if (!running) return null;
|
||||
SendLevelRaw("&4Starting in &f3 &4seconds", true);
|
||||
Thread.Sleep(1000); if (!Running) return null;
|
||||
Thread.Sleep(1000); if (!running) return null;
|
||||
SendLevelRaw("&4Starting in &f2 &4seconds", true);
|
||||
Thread.Sleep(1000); if (!Running) return null;
|
||||
Thread.Sleep(1000); if (!running) return null;
|
||||
SendLevelRaw("&4Starting in &f1 &4second", true);
|
||||
Thread.Sleep(1000); if (!Running) return null;
|
||||
Thread.Sleep(1000); if (!running) return null;
|
||||
SendLevelRaw("", true);
|
||||
int nonRefPlayers = 0;
|
||||
List<Player> players = new List<Player>();
|
||||
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
foreach (Player p in online) {
|
||||
if (!p.Game.Referee && p.level.name.CaselessEq(MapName)) {
|
||||
players.Add(p);
|
||||
nonRefPlayers++;
|
||||
}
|
||||
if (p.Game.Referee || p.level != Map) continue;
|
||||
players.Add(p);
|
||||
nonRefPlayers++;
|
||||
}
|
||||
|
||||
if (!Running) return null;
|
||||
if (!running) return null;
|
||||
if (nonRefPlayers >= 2) return players;
|
||||
Map.ChatLevel("&cNeed 2 or more non-ref players to start a round.");
|
||||
}
|
||||
@ -114,7 +139,7 @@ namespace MCGalaxy.Games {
|
||||
string lastTimeLeft = null;
|
||||
int lastCountdown = -1;
|
||||
|
||||
while (alive.Length > 0 && Running) {
|
||||
while (alive.Length > 0 && running) {
|
||||
Player[] infected = Infected.Items;
|
||||
// Do round end.
|
||||
int seconds = (int)(RoundEnd - DateTime.UtcNow).TotalSeconds;
|
||||
@ -147,23 +172,20 @@ namespace MCGalaxy.Games {
|
||||
int dist = ZSConfig.HitboxPrecision;
|
||||
foreach (Player killer in deadList) {
|
||||
killer.Game.Infected = true;
|
||||
UpdatePlayerColor(killer, InfectCol);
|
||||
aliveList = Alive.Items;
|
||||
|
||||
foreach (Player alive in aliveList) {
|
||||
if (alive == killer) continue;
|
||||
UpdatePlayerColor(alive, alive.color);
|
||||
if (!MovementCheck.InRange(alive, killer, dist)) continue;
|
||||
|
||||
if (killer.Game.Infected && !alive.Game.Infected
|
||||
&& !alive.Game.Referee && !killer.Game.Referee
|
||||
&& killer.level.name.CaselessEq(MapName)
|
||||
&& alive.level.name.CaselessEq(MapName))
|
||||
&& killer.level == Map && alive.level == Map)
|
||||
{
|
||||
InfectPlayer(alive, killer);
|
||||
alive.Game.LastInfecter = killer.name;
|
||||
|
||||
if (lastPlayerToInfect == killer.name) {
|
||||
if (lastKiller == killer.name) {
|
||||
infectCombo++;
|
||||
if (infectCombo >= 2) {
|
||||
killer.SendMessage("You gained " + (2 + infectCombo) + " " + ServerConfig.Currency);
|
||||
@ -174,13 +196,12 @@ namespace MCGalaxy.Games {
|
||||
infectCombo = 0;
|
||||
}
|
||||
|
||||
lastPlayerToInfect = killer.name;
|
||||
lastKiller = killer.name;
|
||||
killer.Game.CurrentInfected++;
|
||||
killer.Game.TotalInfected++;
|
||||
killer.Game.MaxInfected = Math.Max(killer.Game.CurrentInfected, killer.Game.MaxInfected);
|
||||
|
||||
ShowInfectMessage(random, alive, killer);
|
||||
UpdatePlayerColor(alive, InfectCol);
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
}
|
||||
@ -266,10 +287,56 @@ namespace MCGalaxy.Games {
|
||||
"&c" + pKiller.DisplayName + "%S",
|
||||
pAlive.ColoredName + "%S"));
|
||||
}
|
||||
|
||||
bool SetMap(string map) {
|
||||
Picker.QueuedMap = null;
|
||||
Map = LevelInfo.FindExact(map) ?? CmdLoad.LoadLevel(null, map);
|
||||
if (Map == null) return false;
|
||||
|
||||
Map.SaveChanges = false;
|
||||
if (ZSConfig.SetMainLevel) Server.mainLevel = Map;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void UpdatePlayerColor(Player p, string color) {
|
||||
if (p.Game.lastSpawnColor == color) return;
|
||||
p.Game.lastSpawnColor = color;
|
||||
void ChangeLevel(string next) {
|
||||
Map.ChatLevel("The next map has been chosen - &c" + next.ToLower());
|
||||
Map.ChatLevel("Please wait while you are transfered.");
|
||||
LastMap = Map.MapName;
|
||||
|
||||
if (!SetMap(next)) {
|
||||
Map.ChatLevel("&cFailed to change map to " + next);
|
||||
Map.ChatLevel("Continuing ZS on this map again");
|
||||
} else {
|
||||
MoveToNextMap(LastMap);
|
||||
|
||||
Command.all.FindByName("Unload").Use(null, LastMap);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveToNextMap(string lastMap) {
|
||||
Random rnd = new Random();
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
List<Player> players = new List<Player>(online.Length);
|
||||
|
||||
foreach (Player pl in online) {
|
||||
pl.Game.RatedMap = false;
|
||||
pl.Game.PledgeSurvive = false;
|
||||
if (pl.level != Map && pl.level.name.CaselessEq(lastMap)) {
|
||||
players.Add(pl);
|
||||
}
|
||||
}
|
||||
|
||||
while (players.Count > 0) {
|
||||
int i = rnd.Next(0, players.Count);
|
||||
Player pl = players[i];
|
||||
|
||||
pl.SendMessage("Going to the next map - &a" + Map.MapName);
|
||||
PlayerActions.ChangeMap(pl, Map);
|
||||
players.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void RespawnPlayer(Player p) {
|
||||
Entities.GlobalRespawn(p, false);
|
||||
TabList.Add(p, p, Entities.SelfID);
|
||||
}
|
||||
@ -282,7 +349,95 @@ namespace MCGalaxy.Games {
|
||||
HUD.UpdateAllPrimary(this);
|
||||
|
||||
if (!Running) return;
|
||||
Rewards.HandOut(this);
|
||||
Player[] alive = Alive.Items, dead = Infected.Items;
|
||||
Map.ChatLevel("&aThe game has ended!");
|
||||
|
||||
if (alive.Length == 0) Map.ChatLevel("&4Zombies have won this round.");
|
||||
else if (alive.Length == 1) Map.ChatLevel("&2Congratulations to the sole survivor:");
|
||||
else Map.ChatLevel("&2Congratulations to the survivors:");
|
||||
AnnounceWinners(alive, dead);
|
||||
|
||||
Map.Config.RoundsPlayed++;
|
||||
if (alive.Length > 0) {
|
||||
Map.Config.RoundsHumanWon++;
|
||||
foreach (Player p in alive) { IncreaseAliveStats(p); }
|
||||
}
|
||||
|
||||
GiveMoney(alive);
|
||||
Level.SaveSettings(Map);
|
||||
}
|
||||
|
||||
void AnnounceWinners(Player[] alive, Player[] dead) {
|
||||
if (alive.Length > 0) {
|
||||
Map.ChatLevel(alive.Join(p => p.ColoredName));
|
||||
return;
|
||||
}
|
||||
|
||||
int maxKills = 0, count = 0;
|
||||
for (int i = 0; i < dead.Length; i++) {
|
||||
maxKills = Math.Max(maxKills, dead[i].Game.CurrentInfected);
|
||||
}
|
||||
for (int i = 0; i < dead.Length; i++) {
|
||||
if (dead[i].Game.CurrentInfected == maxKills) count++;
|
||||
}
|
||||
|
||||
string group = count == 1 ? " zombie " : " zombies ";
|
||||
string suffix = maxKills == 1 ? " %Skill" : " %Skills";
|
||||
StringFormatter<Player> formatter = p => p.Game.CurrentInfected == maxKills ? p.ColoredName : null;
|
||||
Map.ChatLevel("&8Best" + group + "%S(&b" + maxKills + suffix + "%S)&8: " + dead.Join(formatter));
|
||||
}
|
||||
|
||||
void IncreaseAliveStats(Player p) {
|
||||
if (p.Game.PledgeSurvive) {
|
||||
Player.Message(p, "You received &a5 %3" + ServerConfig.Currency +
|
||||
" %Sfor successfully pledging that you would survive.");
|
||||
p.SetMoney(p.money + 5);
|
||||
}
|
||||
|
||||
p.Game.CurrentRoundsSurvived++;
|
||||
p.Game.TotalRoundsSurvived++;
|
||||
p.Game.MaxRoundsSurvived = Math.Max(p.Game.CurrentRoundsSurvived, p.Game.MaxRoundsSurvived);
|
||||
p.SetPrefix(); // stars before name
|
||||
}
|
||||
|
||||
void GiveMoney(Player[] alive) {
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
Random rand = new Random();
|
||||
|
||||
foreach (Player pl in online) {
|
||||
if (pl.level != Map) continue;
|
||||
pl.Game.ResetInvisibility();
|
||||
int reward = GetMoneyReward(pl, alive, rand);
|
||||
|
||||
if (reward == -1) {
|
||||
pl.SendMessage("You may not hide inside a block! No " + ServerConfig.Currency + " for you."); reward = 0;
|
||||
} else if (reward > 0) {
|
||||
pl.SendMessage(Colors.gold + "You gained " + reward + " " + ServerConfig.Currency);
|
||||
}
|
||||
|
||||
pl.SetMoney(pl.money + reward);
|
||||
pl.Game.ResetZombieState();
|
||||
if (pl.Game.Referee) {
|
||||
pl.SendMessage("You gained one " + ServerConfig.Currency + " because you're a ref. Would you like a medal as well?");
|
||||
pl.SetMoney(pl.money + 1);
|
||||
}
|
||||
|
||||
ZSGame.RespawnPlayer(pl);
|
||||
HUD.UpdateTertiary(pl);
|
||||
}
|
||||
}
|
||||
|
||||
static int GetMoneyReward(Player pl, Player[] alive, Random rand) {
|
||||
if (pl.CheckIfInsideBlock()) return -1;
|
||||
|
||||
if (alive.Length == 0) {
|
||||
return rand.Next(1 + pl.Game.CurrentInfected, 5 + pl.Game.CurrentInfected);
|
||||
} else if (alive.Length == 1 && !pl.Game.Infected) {
|
||||
return rand.Next(5, 10);
|
||||
} else if (alive.Length > 1 && !pl.Game.Infected) {
|
||||
return rand.Next(2, 6);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -41,31 +41,30 @@ namespace MCGalaxy.Games {
|
||||
public int TotalRounds, MaxRounds, TotalInfected, MaxInfected;
|
||||
}
|
||||
|
||||
public sealed partial class ZSGame {
|
||||
|
||||
public const string InfectCol = "&infect";
|
||||
public sealed partial class ZSGame : RoundsGame {
|
||||
public override string GameName { get { return "Zombie survival"; } }
|
||||
public override bool TeleportAllowed { get { return !RoundInProgress; } }
|
||||
public override bool Running { get { return running; } }
|
||||
|
||||
public LevelPicker Picker = new ZSLevelPicker();
|
||||
public DateTime RoundStart, RoundEnd;
|
||||
public string LastLevelName = "";
|
||||
public string LastMap = "";
|
||||
public VolatileArray<Player> Alive = new VolatileArray<Player>();
|
||||
public VolatileArray<Player> Infected = new VolatileArray<Player>();
|
||||
public string QueuedZombie;
|
||||
public VolatileArray<BountyData> Bounties = new VolatileArray<BountyData>();
|
||||
|
||||
List<string> infectMessages = new List<string>();
|
||||
string lastPlayerToInfect = "";
|
||||
int infectCombo = 0;
|
||||
List<string> infectMessages = new List<string>();
|
||||
bool running;
|
||||
ZSPlugin plugin = new ZSPlugin();
|
||||
|
||||
public void Start(Level level, int rounds) {
|
||||
running = true;
|
||||
RoundInProgress = false;
|
||||
RoundInProgress = false;
|
||||
if (!SetStartLevel(level)) { running = false; return; }
|
||||
|
||||
RoundsLeft = rounds;
|
||||
HookStats();
|
||||
if (plugin.Game == null) { plugin.Game = this; plugin.Load(false); }
|
||||
HookEventHandlers();
|
||||
|
||||
Thread t = new Thread(RunGame);
|
||||
t.Name = "MCG_ZombieGame";
|
||||
@ -73,55 +72,25 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
|
||||
bool SetStartLevel(Level level) {
|
||||
string mapName;
|
||||
if (level == null) {
|
||||
List<string> levels = Picker.GetCandidateLevels();
|
||||
if (levels == null) return false;
|
||||
|
||||
MapName = LevelPicker.GetRandomLevel(new Random(), levels);
|
||||
Map = LevelInfo.FindExact(MapName)
|
||||
?? CmdLoad.LoadLevel(null, MapName);
|
||||
if (Map == null) return false;
|
||||
List<string> maps = Picker.GetCandidateMaps();
|
||||
if (maps == null) return false;
|
||||
mapName = LevelPicker.GetRandomMap(new Random(), maps);
|
||||
} else {
|
||||
MapName = level.name;
|
||||
Map = level;
|
||||
}
|
||||
mapName = level.name;
|
||||
}
|
||||
if (!SetMap(mapName)) return false;
|
||||
|
||||
Map.SaveChanges = false;
|
||||
Chat.MessageGlobal("A game of zombie survival is starting on: {0}", MapName);
|
||||
Chat.MessageGlobal("A game of zombie survival is starting on: {0}", Map.ColoredName);
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
foreach (Player p in players) {
|
||||
if (p.level != Map) continue;
|
||||
PlayerJoinedLevel(p, p.level, p.level);
|
||||
}
|
||||
|
||||
if (ZSConfig.SetMainLevel)
|
||||
Server.mainLevel = Map;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary> If there are no infected players left, randomly selected one of the alive players to continue the infection. </summary>
|
||||
public void AssignFirstZombie() {
|
||||
if (!Running || !RoundInProgress || Infected.Count > 0) return;
|
||||
Random random = new Random();
|
||||
Player[] alive = Alive.Items;
|
||||
if (alive.Length == 0) return;
|
||||
int index = random.Next(alive.Length);
|
||||
|
||||
while (alive[index].Game.Referee || !alive[index].level.name.CaselessEq(MapName)) {
|
||||
if (index >= alive.Length - 1) {
|
||||
index = 0;
|
||||
alive = Alive.Items;
|
||||
if (alive.Length == 0) return;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
Player zombie = alive[index];
|
||||
Map.ChatLevel("&c" + zombie.DisplayName + " %Scontinued the infection!");
|
||||
InfectPlayer(zombie, null);
|
||||
}
|
||||
|
||||
public void InfectPlayer(Player p, Player killer) {
|
||||
if (!RoundInProgress || p == null) return;
|
||||
Infected.Add(p);
|
||||
@ -130,7 +99,9 @@ namespace MCGalaxy.Games {
|
||||
p.Game.CurrentRoundsSurvived = 0;
|
||||
p.Game.TimeInfected = DateTime.UtcNow;
|
||||
p.SetPrefix();
|
||||
|
||||
ResetPlayerState(p, true);
|
||||
RespawnPlayer(p);
|
||||
|
||||
CheckHumanPledge(p, killer);
|
||||
CheckBounty(p, killer);
|
||||
@ -140,16 +111,16 @@ namespace MCGalaxy.Games {
|
||||
if (!RoundInProgress || p == null) return;
|
||||
Infected.Remove(p);
|
||||
Alive.Add(p);
|
||||
|
||||
ResetPlayerState(p, false);
|
||||
RespawnPlayer(p);
|
||||
}
|
||||
|
||||
void ResetPlayerState(Player p, bool infected) {
|
||||
p.Game.Infected = infected;
|
||||
p.Game.BlocksLeft = infected ? 25 : 50;
|
||||
string col = infected ? Colors.red : p.color;
|
||||
|
||||
ResetInvisibility(p);
|
||||
UpdatePlayerColor(p, col);
|
||||
HUD.UpdateAllPrimary(this);
|
||||
HUD.UpdateTertiary(p);
|
||||
}
|
||||
@ -161,61 +132,15 @@ namespace MCGalaxy.Games {
|
||||
Entities.GlobalSpawn(p, false);
|
||||
}
|
||||
|
||||
void ChangeLevel(string next) {
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
if (Map != null) {
|
||||
Level.SaveSettings(Map);
|
||||
Map.ChatLevel("The next map has been chosen - " + Colors.red + next.ToLower());
|
||||
Map.ChatLevel("Please wait while you are transfered.");
|
||||
}
|
||||
string lastLevel = MapName;
|
||||
|
||||
MapName = next;
|
||||
Picker.QueuedMap = null;
|
||||
CmdLoad.LoadLevel(null, next);
|
||||
Map = LevelInfo.FindExact(next);
|
||||
Map.SaveChanges = false;
|
||||
if (ZSConfig.SetMainLevel)
|
||||
Server.mainLevel = Map;
|
||||
|
||||
online = PlayerInfo.Online.Items;
|
||||
List<Player> players = new List<Player>(online.Length);
|
||||
foreach (Player pl in online) {
|
||||
pl.Game.RatedMap = false;
|
||||
pl.Game.PledgeSurvive = false;
|
||||
if (!pl.level.name.CaselessEq(next) && pl.level.name.CaselessEq(lastLevel)) {
|
||||
players.Add(pl);
|
||||
}
|
||||
}
|
||||
JoinInRandomOrder(players, next);
|
||||
|
||||
if (LastLevelName.Length > 0) {
|
||||
Command.all.FindByName("Unload").Use(null, LastLevelName);
|
||||
}
|
||||
LastLevelName = next;
|
||||
}
|
||||
|
||||
static void JoinInRandomOrder(List<Player> players, string next) {
|
||||
Random rnd = new Random();
|
||||
while (players.Count > 0) {
|
||||
int index = rnd.Next(0, players.Count);
|
||||
Player pl = players[index];
|
||||
|
||||
pl.SendMessage("Going to the next map - &a" + next);
|
||||
PlayerActions.ChangeMap(pl, next);
|
||||
players.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
public override void End() {
|
||||
running = false;
|
||||
RoundsLeft = 0;
|
||||
RoundInProgress = false;
|
||||
RoundStart = DateTime.MinValue;
|
||||
RoundEnd = DateTime.MinValue;
|
||||
if (plugin.Game != null) { plugin.Game = null; plugin.Unload(false); }
|
||||
UnhookEventHandlers();
|
||||
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
Player[] online = PlayerInfo.Online.Items;
|
||||
Alive.Clear();
|
||||
Infected.Clear();
|
||||
|
||||
@ -229,12 +154,11 @@ namespace MCGalaxy.Games {
|
||||
ResetInvisibility(pl);
|
||||
pl.SetPrefix();
|
||||
|
||||
if (pl.level == null || !pl.level.name.CaselessEq(MapName)) continue;
|
||||
if (pl.level == null || pl.level != Map) continue;
|
||||
HUD.Reset(pl);
|
||||
}
|
||||
|
||||
LastLevelName = "";
|
||||
MapName = "";
|
||||
LastMap = "";
|
||||
Map = null;
|
||||
UnhookStats();
|
||||
}
|
||||
@ -246,6 +170,111 @@ namespace MCGalaxy.Games {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void PlayerLeftGame(Player p) {
|
||||
Alive.Remove(p);
|
||||
Infected.Remove(p);
|
||||
p.Game.Infected = false;
|
||||
RemoveBounties(p);
|
||||
|
||||
AssignFirstZombie();
|
||||
HUD.UpdateAllPrimary(this);
|
||||
}
|
||||
|
||||
public override bool HandlesChatMessage(Player p, string message) {
|
||||
if (!Running || (p.level == null || p.level != Map)) return false;
|
||||
if (Picker.Voting && Picker.HandlesMessage(p, message)) return true;
|
||||
|
||||
if (message[0] == '~' && message.Length > 1) {
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
string type = p.Game.Infected ? " &cto zombies%S: " : " &ato humans%S: ";
|
||||
string toSend = p.ColoredName + type + message.Substring(1);
|
||||
|
||||
foreach (Player pl in players) {
|
||||
if (pl.level != Map || !Chat.NotIgnoring(pl, p)) continue;
|
||||
if (pl.Game.Referee || pl.Game.Infected == p.Game.Infected) {
|
||||
pl.SendMessage(toSend);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (message[0] == '`' && message.Length > 1) {
|
||||
if (p.Game.Team == null) {
|
||||
Player.Message(p, "You are not on a team, so cannot send a team message."); return true;
|
||||
}
|
||||
p.Game.Team.Chat(p, message.Substring(1));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RemoveBounties(Player p) {
|
||||
BountyData[] bounties = Bounties.Items;
|
||||
foreach (BountyData b in bounties) {
|
||||
if (!(b.Origin.CaselessEq(p.name) || b.Target.CaselessEq(p.name))) continue;
|
||||
|
||||
string target = PlayerInfo.GetColoredName(p, b.Target);
|
||||
Map.ChatLevel("Bounty on " + target + " %Sis no longer active.");
|
||||
Bounties.Remove(b);
|
||||
|
||||
Player setter = PlayerInfo.FindExact(b.Origin);
|
||||
if (setter != null) setter.SetMoney(setter.money + b.Amount);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PlayerJoinedLevel(Player p, Level lvl, Level oldLvl) {
|
||||
p.SendCpeMessage(CpeMessageType.BottomRight3, "");
|
||||
p.SendCpeMessage(CpeMessageType.BottomRight2, "");
|
||||
p.SendCpeMessage(CpeMessageType.BottomRight1, "");
|
||||
|
||||
if (RoundInProgress && lvl == Map && Running && p != null) {
|
||||
Player.Message(p, "You joined in the middle of a round. &cYou are now infected!");
|
||||
p.Game.BlocksLeft = 25;
|
||||
InfectPlayer(p, null);
|
||||
}
|
||||
if (RoundInProgress && oldLvl == Map && lvl != Map) {
|
||||
PlayerLeftGame(p);
|
||||
}
|
||||
|
||||
if (lvl == Map) {
|
||||
double startLeft = (RoundStart - DateTime.UtcNow).TotalSeconds;
|
||||
if (startLeft >= 0)
|
||||
Player.Message(p, "%a" + (int)startLeft + " %Sseconds left until the round starts. %aRun!");
|
||||
Player.Message(p, "This map has &a" + Map.Config.Likes +
|
||||
" likes %Sand &c" + Map.Config.Dislikes + " dislikes");
|
||||
Player.Message(p, "This map's win chance is &a" + Map.WinChance + "%S%");
|
||||
|
||||
if (Map.Config.Authors.Length > 0) {
|
||||
string[] authors = Map.Config.Authors.Replace(" ", "").Split(',');
|
||||
Player.Message(p, "It was created by {0}",
|
||||
authors.Join(n => PlayerInfo.GetColoredName(p, n)));
|
||||
}
|
||||
|
||||
HUD.UpdatePrimary(this, p);
|
||||
HUD.UpdateSecondary(this, p);
|
||||
HUD.UpdateTertiary(p);
|
||||
|
||||
if (Picker.Voting) Picker.SendVoteMessage(p);
|
||||
return;
|
||||
}
|
||||
|
||||
p.SetPrefix();
|
||||
HUD.Reset(p);
|
||||
Alive.Remove(p);
|
||||
Infected.Remove(p);
|
||||
|
||||
if (oldLvl != null && oldLvl == Map) {
|
||||
HUD.UpdateAllPrimary(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void AdjustPrefix(Player p, ref string prefix) {
|
||||
int winStreak = p.Game.CurrentRoundsSurvived;
|
||||
|
||||
if (winStreak == 1) prefix += "&4*" + p.color;
|
||||
else if (winStreak == 2) prefix += "&7*" + p.color;
|
||||
else if (winStreak == 3) prefix += "&6*" + p.color;
|
||||
else if (winStreak > 0) prefix += "&6" + winStreak + p.color;
|
||||
}
|
||||
|
||||
static string[] defMessages = new string[] { "{0} WIKIWOO'D {1}", "{0} stuck their teeth into {1}",
|
||||
"{0} licked {1}'s brain ", "{0} danubed {1}", "{0} made {1} meet their maker", "{0} tripped {1}",
|
||||
@ -389,5 +418,31 @@ namespace MCGalaxy.Games {
|
||||
Player.Message(p, " Infected &a{0} %Splayers (max &e{1}%S)", infected, infectedMax);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class ZSLevelPicker : LevelPicker {
|
||||
|
||||
public override List<string> GetCandidateMaps() {
|
||||
List<string> maps = null;
|
||||
bool useLevelList = ZSConfig.LevelList.Count > 0;
|
||||
|
||||
if (useLevelList) {
|
||||
maps = new List<string>(ZSConfig.LevelList);
|
||||
} else {
|
||||
string[] files = LevelInfo.AllMapFiles();
|
||||
for (int i = 0; i < files.Length; i++) {
|
||||
files[i] = Path.GetFileNameWithoutExtension(files[i]);
|
||||
}
|
||||
maps = new List<string>(files);
|
||||
}
|
||||
|
||||
foreach (string ignore in ZSConfig.IgnoredLevelList) { maps.Remove(ignore); }
|
||||
if (maps.Count < 3) {
|
||||
string group = useLevelList ? "in your level list " : "";
|
||||
Logger.Log(LogType.Warning, "You must have more than 3 levels {0}to change levels in Zombie Survival", group);
|
||||
return null;
|
||||
}
|
||||
return maps;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
/*
|
||||
Copyright 2010 MCLawl Team -
|
||||
Created by Snowl (David D.) and Cazzar (Cayde D.)
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.osedu.org/licenses/ECL-2.0
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using MCGalaxy.Games.ZS;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
public sealed partial class ZSGame {
|
||||
|
||||
public LevelPicker Picker = new ZSLevelPicker();
|
||||
public override bool TeleportAllowed { get { return !RoundInProgress; } }
|
||||
public override bool Running { get { return running; } }
|
||||
|
||||
public override void PlayerLeftGame(Player p) {
|
||||
Alive.Remove(p);
|
||||
Infected.Remove(p);
|
||||
p.Game.Infected = false;
|
||||
RemoveBounties(p);
|
||||
|
||||
AssignFirstZombie();
|
||||
HUD.UpdateAllPrimary(this);
|
||||
}
|
||||
|
||||
public override bool HandlesChatMessage(Player p, string message) {
|
||||
if (!Running || (p.level == null || !p.level.name.CaselessEq(MapName))) return false;
|
||||
if (Server.votingforlevel && HandleVote(p, message)) return true;
|
||||
|
||||
if (message[0] == '~' && message.Length > 1) {
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
string type = p.Game.Infected ? " &cto zombies%S: " : " &ato humans%S: ";
|
||||
string toSend = p.ColoredName + type + message.Substring(1);
|
||||
|
||||
foreach (Player pl in players) {
|
||||
if (!pl.level.name.CaselessEq(MapName) || !Chat.NotIgnoring(pl, p)) continue;
|
||||
if (pl.Game.Referee || pl.Game.Infected == p.Game.Infected) {
|
||||
pl.SendMessage(toSend);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (message[0] == '`' && message.Length > 1) {
|
||||
if (p.Game.Team == null) {
|
||||
Player.Message(p, "You are not on a team, so cannot send a team message."); return true;
|
||||
}
|
||||
p.Game.Team.Chat(p, message.Substring(1));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HandleVote(Player p, string message) {
|
||||
message = message.ToLower();
|
||||
if (Player.CheckVote(message, p, "1", "one", ref Picker.Votes1) ||
|
||||
Player.CheckVote(message, p, "2", "two", ref Picker.Votes2) ||
|
||||
Player.CheckVote(message, p, "3", "three", ref Picker.Votes3))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void RemoveBounties(Player p) {
|
||||
BountyData[] bounties = Bounties.Items;
|
||||
foreach (BountyData b in bounties) {
|
||||
if (!(b.Origin.CaselessEq(p.name) || b.Target.CaselessEq(p.name))) continue;
|
||||
|
||||
string target = PlayerInfo.GetColoredName(p, b.Target);
|
||||
Map.ChatLevel("Bounty on " + target + " %Sis no longer active.");
|
||||
Bounties.Remove(b);
|
||||
|
||||
Player setter = PlayerInfo.FindExact(b.Origin);
|
||||
if (setter != null) setter.SetMoney(setter.money + b.Amount);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PlayerJoinedLevel(Player p, Level lvl, Level oldLvl) {
|
||||
p.SendCpeMessage(CpeMessageType.BottomRight3, "");
|
||||
p.SendCpeMessage(CpeMessageType.BottomRight2, "");
|
||||
p.SendCpeMessage(CpeMessageType.BottomRight1, "");
|
||||
if (RoundInProgress && lvl.name.CaselessEq(MapName)) {
|
||||
if (Running && p != null) {
|
||||
Player.Message(p, "You joined in the middle of a round. &cYou are now infected!");
|
||||
p.Game.BlocksLeft = 25;
|
||||
InfectPlayer(p, null);
|
||||
}
|
||||
}
|
||||
if (RoundInProgress && oldLvl == Map && lvl != Map) {
|
||||
PlayerLeftGame(p);
|
||||
}
|
||||
|
||||
if (lvl.name.CaselessEq(MapName)) {
|
||||
double startLeft = (RoundStart - DateTime.UtcNow).TotalSeconds;
|
||||
if (startLeft >= 0)
|
||||
Player.Message(p, "%a" + (int)startLeft + " %Sseconds left until the round starts. %aRun!");
|
||||
Player.Message(p, "This map has &a" + Map.Config.Likes +
|
||||
" likes %Sand &c" + Map.Config.Dislikes + " dislikes");
|
||||
Player.Message(p, "This map's win chance is &a" + Map.WinChance + "%S%");
|
||||
|
||||
if (Map.Config.Authors.Length > 0) {
|
||||
string[] authors = Map.Config.Authors.Replace(" ", "").Split(',');
|
||||
Player.Message(p, "It was created by {0}",
|
||||
authors.Join(n => PlayerInfo.GetColoredName(p, n)));
|
||||
}
|
||||
|
||||
HUD.UpdatePrimary(this, p);
|
||||
HUD.UpdateSecondary(this, p);
|
||||
HUD.UpdateTertiary(p);
|
||||
|
||||
if (Server.votingforlevel) Picker.SendVoteMessage(p);
|
||||
return;
|
||||
}
|
||||
|
||||
p.SetPrefix();
|
||||
HUD.Reset(p);
|
||||
Alive.Remove(p);
|
||||
Infected.Remove(p);
|
||||
if (oldLvl != null && oldLvl.name.CaselessEq(MapName))
|
||||
HUD.UpdateAllPrimary(this);
|
||||
}
|
||||
|
||||
public override void OnHeartbeat(ref string name) {
|
||||
if (!Running || !ZSConfig.IncludeMapInHeartbeat || MapName == null) return;
|
||||
name += " (map: " + MapName + ")";
|
||||
}
|
||||
|
||||
public override void AdjustPrefix(Player p, ref string prefix) {
|
||||
int winStreak = p.Game.CurrentRoundsSurvived;
|
||||
|
||||
if (winStreak == 1) prefix += "&4*" + p.color;
|
||||
else if (winStreak == 2) prefix += "&7*" + p.color;
|
||||
else if (winStreak == 3) prefix += "&6*" + p.color;
|
||||
else if (winStreak > 0) prefix += "&6" + winStreak + p.color;
|
||||
}
|
||||
}
|
||||
}
|
@ -117,10 +117,10 @@ namespace MCGalaxy {
|
||||
|
||||
public bool ShouldShowJoinMessage(Level prev) {
|
||||
ZSGame zs = Server.zombie;
|
||||
if (zs.Running && name.CaselessEq(zs.MapName) &&
|
||||
(prev == this || zs.LastLevelName.Length == 0 || prev.name.CaselessEq(zs.LastLevelName)))
|
||||
if (zs.Running && this == zs.Map &&
|
||||
(prev == this || zs.LastMap.Length == 0 || prev.name.CaselessEq(zs.LastMap)))
|
||||
return false;
|
||||
if (Server.lava.active && Server.lava.HasMap(name))
|
||||
if (Server.lava.Running && Server.lava.HasMap(name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -128,10 +128,8 @@ namespace MCGalaxy {
|
||||
/// <summary> The currently active game running on this map,
|
||||
/// or null if there is no game running. </summary>
|
||||
public IGame CurrentGame() {
|
||||
if (Server.zombie.Running && name.CaselessEq(Server.zombie.MapName))
|
||||
return Server.zombie;
|
||||
if (Server.lava.active && Server.lava.map == this)
|
||||
return Server.lava;
|
||||
if (Server.zombie.Running && Server.zombie.Map == this) return Server.zombie;
|
||||
if (Server.lava.Running && Server.lava.Map == this) return Server.lava;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -148,7 +146,6 @@ namespace MCGalaxy {
|
||||
|
||||
public bool Unload(bool silent = false, bool save = true) {
|
||||
if (Server.mainLevel == this || IsMuseum) return false;
|
||||
if (Server.lava.active && Server.lava.map == this) return false;
|
||||
OnLevelUnloadEvent.Call(this);
|
||||
if (cancelunload) {
|
||||
Logger.Log(LogType.SystemActivity, "Unload canceled by Plugin! (Map: {0})", name);
|
||||
|
@ -486,32 +486,31 @@
|
||||
<Compile Include="Events\ModActionEvent.cs" />
|
||||
<Compile Include="Events\PlayerClick.cs" />
|
||||
<Compile Include="Events\PlayerEvents.cs" />
|
||||
<Compile Include="Events\ServerEvents.cs" />
|
||||
<Compile Include="Games\Countdown\CountdownGame.cs" />
|
||||
<Compile Include="Games\Countdown\CountdownGame.Plugin.cs" />
|
||||
<Compile Include="Games\Countdown\CountdownMapGen.cs" />
|
||||
<Compile Include="Games\Countdown\CountdownPlugin.cs" />
|
||||
<Compile Include="Games\CTF\CtfConfig.cs" />
|
||||
<Compile Include="Games\CTF\CtfPlugin.cs" />
|
||||
<Compile Include="Games\CTF\CtfTeam.cs" />
|
||||
<Compile Include="Games\CTF\CtfGame.Plugin.cs" />
|
||||
<Compile Include="Games\CTF\CtfGame.Round.cs" />
|
||||
<Compile Include="Games\CTF\CtfTeamOld.cs" />
|
||||
<Compile Include="Games\GameProps.cs" />
|
||||
<Compile Include="Games\IGame.cs" />
|
||||
<Compile Include="Games\LavaSurvival\LavaSurvival.Game.cs" />
|
||||
<Compile Include="Games\LavaSurvival\LavaSurvival.cs" />
|
||||
<Compile Include="Games\LavaSurvival\LavaSurvival.Settings.cs" />
|
||||
<Compile Include="Games\LavaSurvival\LSGame.Plugin.cs" />
|
||||
<Compile Include="Games\LavaSurvival\LSGame.cs" />
|
||||
<Compile Include="Games\LavaSurvival\LSConfig.cs" />
|
||||
<Compile Include="Games\LavaSurvival\LSGame.Round.cs" />
|
||||
<Compile Include="Games\LevelPicker.cs" />
|
||||
<Compile Include="Games\MovementCheck.cs" />
|
||||
<Compile Include="Games\Team.cs" />
|
||||
<Compile Include="Games\TntWars\TntWars.cs" />
|
||||
<Compile Include="Games\TntWars\TntWarsConfig.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\LevelPicker.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\HUD.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\Pillaring.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZombieGame.Core.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\Rewards.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZombieGame.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZombieGame.Game.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZSGame.Round.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZSGame.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZSGame.Plugin.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZSConfig.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZSPlugin.cs" />
|
||||
<Compile Include="Generator\AdvNoiseGen.cs" />
|
||||
<Compile Include="Generator\fCraft\MapGenerator.cs" />
|
||||
<Compile Include="Generator\fCraft\MapGeneratorArgs.cs" />
|
||||
|
@ -19,6 +19,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using MCGalaxy.Events.ServerEvents;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace MCGalaxy.Network {
|
||||
@ -59,7 +60,7 @@ namespace MCGalaxy.Network {
|
||||
|
||||
public override string GetHeartbeatData() {
|
||||
string name = ServerConfig.Name;
|
||||
Server.zombie.OnHeartbeat(ref name);
|
||||
OnSendingHeartbeatEvent.Call(this, ref name);
|
||||
name = Colors.Strip(name);
|
||||
|
||||
return
|
||||
|
@ -243,7 +243,7 @@ namespace MCGalaxy {
|
||||
|
||||
|
||||
public bool cancelcommand, cancelchat, cancelmove, cancelBlock, cancelmysql;
|
||||
public bool cancelmessage, cancellogin, cancelconnecting;
|
||||
public bool cancelmessage, cancellogin, cancelconnecting, cancelDeath;
|
||||
|
||||
/// <summary> Called when a player removes or places a block.
|
||||
/// NOTE: Currently this prevents the OnBlockChange event from being called. </summary>
|
||||
|
@ -77,7 +77,7 @@ namespace MCGalaxy {
|
||||
RevertBlock(x, y, z); return;
|
||||
}
|
||||
|
||||
if ( Server.lava.active && Server.lava.HasPlayer(this) && Server.lava.IsPlayerDead(this) ) {
|
||||
if ( Server.lava.running && Server.lava.Map == level && Server.lava.IsPlayerDead(this) ) {
|
||||
SendMessage("You are out of the round, and cannot build.");
|
||||
RevertBlock(x, y, z); return;
|
||||
}
|
||||
@ -435,12 +435,13 @@ namespace MCGalaxy {
|
||||
|
||||
bool Moved() { return lastRot.RotY != Rot.RotY || lastRot.HeadX != Rot.HeadX; }
|
||||
|
||||
public void HandleDeath(BlockID block, string customMsg = "", bool explode = false, bool immediate = false) {
|
||||
OnPlayerDeathEvent.Call(this, block);
|
||||
public bool HandleDeath(BlockID block, string customMsg = "", bool explode = false, bool immediate = false) {
|
||||
if (!immediate && lastDeath.AddSeconds(2) > DateTime.UtcNow) return false;
|
||||
if (invincible || hidden) return false;
|
||||
|
||||
if (Server.lava.active && Server.lava.HasPlayer(this) && Server.lava.IsPlayerDead(this)) return;
|
||||
if (!immediate && lastDeath.AddSeconds(2) > DateTime.UtcNow) return;
|
||||
if (!level.Config.KillerBlocks || invincible || hidden) return;
|
||||
cancelDeath = false;
|
||||
OnPlayerDeathEvent.Call(this, block);
|
||||
if (cancelDeath) { cancelDeath = false; return false; }
|
||||
|
||||
onTrain = false; trainInvincible = false; trainGrab = false;
|
||||
ushort x = (ushort)Pos.BlockX, y = (ushort)Pos.BlockY, z = (ushort)Pos.BlockZ;
|
||||
@ -463,12 +464,7 @@ namespace MCGalaxy {
|
||||
|
||||
if (PlayingTntWars) {
|
||||
TntWarsKillStreak = 0;
|
||||
TntWarsScoreMultiplier = 1f;
|
||||
} else if ( Server.lava.active && Server.lava.HasPlayer(this) ) {
|
||||
if (!Server.lava.IsPlayerDead(this)) {
|
||||
Server.lava.KillPlayer(this);
|
||||
Command.all.FindByName("Spawn").Use(this, "");
|
||||
}
|
||||
TntWarsScoreMultiplier = 1.0f;
|
||||
} else {
|
||||
Command.all.FindByName("Spawn").Use(this, "");
|
||||
TimesDied++;
|
||||
@ -476,9 +472,11 @@ namespace MCGalaxy {
|
||||
if (TimesDied > short.MaxValue) TimesDied = short.MaxValue;
|
||||
}
|
||||
|
||||
if (ServerConfig.AnnounceDeathCount && (TimesDied > 0 && TimesDied % 10 == 0))
|
||||
if (ServerConfig.AnnounceDeathCount && (TimesDied > 0 && TimesDied % 10 == 0)) {
|
||||
Chat.MessageLevel(this, ColoredName + " %Shas died &3" + TimesDied + " times", false, level);
|
||||
}
|
||||
lastDeath = DateTime.UtcNow;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleChat(byte[] buffer, int offset) {
|
||||
@ -502,17 +500,6 @@ namespace MCGalaxy {
|
||||
// People who are muted can't speak or vote
|
||||
if (muted) { SendMessage("You are muted."); return; } //Muted: Only allow commands
|
||||
|
||||
// Lava Survival map vote recorder
|
||||
if ( Server.lava.HasPlayer(this) && Server.lava.HasVote(text.ToLower()) ) {
|
||||
if ( Server.lava.AddVote(this, text.ToLower()) ) {
|
||||
SendMessage("Your vote for &5" + text.ToLower().Capitalize() + " %Shas been placed. Thanks!");
|
||||
Server.lava.map.ChatLevelOps(name + " voted for &5" + text.ToLower().Capitalize() + "%S.");
|
||||
return;
|
||||
} else {
|
||||
SendMessage("&cYou already voted!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Filter out bad words
|
||||
if (ServerConfig.ProfanityFiltering) text = ProfanityFilter.Parse(text);
|
||||
|
||||
|
@ -148,7 +148,6 @@ namespace MCGalaxy {
|
||||
Logger.Log(LogType.UserActivity, "{0} [{1}] connected using {2}.", name, ip, appName);
|
||||
}
|
||||
Game.InfectMessages = PlayerDB.GetInfectMessages(this);
|
||||
Server.lava.PlayerJoinedServer(this);
|
||||
|
||||
Position pos = level.SpawnPos;
|
||||
byte yaw = level.rotx, pitch = level.roty;
|
||||
|
@ -457,7 +457,7 @@ namespace MCGalaxy {
|
||||
// Mark callback cancelled selection
|
||||
if (selCallback == null) return;
|
||||
|
||||
selIndex++;
|
||||
selIndex++;
|
||||
if (selIndex == 1 && selTitle != null) {
|
||||
SendCpeMessage(CpeMessageType.BottomRight2, "Mark #1" + FormatSelectionMark(selMarks[0]));
|
||||
} else if (selIndex == 2 && selTitle != null) {
|
||||
|
@ -51,7 +51,7 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
if (!p.level.Props[block].KillerBlock) continue;
|
||||
if (block == Block.TNT_Explosion && p.PlayingTntWars) continue; // TODO: hardcoded behaviour is icky
|
||||
if (block == Block.Train && p.trainInvincible) continue;
|
||||
p.HandleDeath(block);
|
||||
if (p.level.Config.KillerBlocks) p.HandleDeath(block);
|
||||
}
|
||||
|
||||
if (!hitWalkthrough) p.lastWalkthrough = -1;
|
||||
@ -71,8 +71,9 @@ namespace MCGalaxy.Blocks.Physics {
|
||||
if (!CollideType.IsSolid(collide)) continue;
|
||||
|
||||
int fallHeight = p.startFallY - bb.Min.Y;
|
||||
if (fallHeight > p.level.Config.FallHeight * 32)
|
||||
if (fallHeight > p.level.Config.FallHeight * 32) {
|
||||
p.HandleDeath(Block.Air, null, false, true);
|
||||
}
|
||||
|
||||
p.startFallY = -1;
|
||||
return;
|
||||
|
@ -92,9 +92,9 @@ namespace MCGalaxy {
|
||||
public static ZSGame zombie;
|
||||
|
||||
public static int YesVotes = 0, NoVotes = 0;
|
||||
public static bool voting = false, votingforlevel = false;
|
||||
public static bool voting = false;
|
||||
|
||||
public static LavaSurvival lava;
|
||||
public static LSGame lava;
|
||||
public static CountdownGame Countdown;
|
||||
|
||||
public static Scheduler MainScheduler = new Scheduler("MCG_MainScheduler");
|
||||
|
@ -99,7 +99,7 @@ namespace MCGalaxy {
|
||||
MoveSqliteDll();
|
||||
MoveOutdatedFiles();
|
||||
|
||||
lava = new LavaSurvival();
|
||||
lava = new LSGame();
|
||||
zombie = new ZSGame();
|
||||
Countdown = new CountdownGame();
|
||||
LoadAllSettings();
|
||||
|
@ -67,11 +67,12 @@ namespace MCGalaxy.Maths {
|
||||
|
||||
|
||||
public override string ToString() {
|
||||
return X + "," + Y + "," + Z;
|
||||
return X + ", " + Y + ", " + Z;
|
||||
}
|
||||
|
||||
public string ToString(string separator) {
|
||||
return String.Format("{1}{0}{2}{0}{3}", separator, X, Y, Z);
|
||||
public static Vec3U16 Parse(string input) {
|
||||
string[] p = input.Replace(" ", "").Split(',');
|
||||
return new Vec3U16(ushort.Parse(p[0]), ushort.Parse(p[1]), ushort.Parse(p[2]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,14 +167,9 @@ namespace MCGalaxy.Maths {
|
||||
public static bool operator != (Vec3S32 a, Vec3S32 b) {
|
||||
return a.X != b.X || a.Y != b.Y || a.Z != b.Z;
|
||||
}
|
||||
|
||||
|
||||
public override string ToString() {
|
||||
return X + "," + Y + "," + Z;
|
||||
}
|
||||
|
||||
public string ToString(string separator) {
|
||||
return String.Format("{1}{0}{2}{0}{3}", separator, X, Y, Z);
|
||||
return X + ", " + Y + ", " + Z;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user