More work on games rewrite

This commit is contained in:
UnknownShadow200 2018-05-08 20:40:54 +10:00
parent 773e9f8152
commit 91b8bf44ac
50 changed files with 1547 additions and 1703 deletions

View File

@ -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);

View File

@ -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)); }
}
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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.";

View File

@ -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();
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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) {

View File

@ -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") {

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}
}
}

View 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]);
}
}
}
}
}

View File

@ -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) {

View 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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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); }
}
}

View File

@ -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);
}
}
}

View File

@ -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,
}
}

View File

@ -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;

View File

@ -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();

View File

@ -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];
}
}

View 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);
}
}
}
}

View File

@ -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.");
}
}
}

View 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"));
}
}
}
}
}

View File

@ -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"));
}
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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.")]

View File

@ -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 + ")";
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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" />

View File

@ -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

View File

@ -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>

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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");

View File

@ -99,7 +99,7 @@ namespace MCGalaxy {
MoveSqliteDll();
MoveOutdatedFiles();
lava = new LavaSurvival();
lava = new LSGame();
zombie = new ZSGame();
Countdown = new CountdownGame();
LoadAllSettings();

View File

@ -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;
}
}