mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-24 05:03:34 -04:00
Rewrite gun to be more modular
This commit is contained in:
parent
4ed9ded251
commit
05a3de6fbe
@ -15,97 +15,41 @@
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using MCGalaxy.Maths;
|
||||
using MCGalaxy.Tasks;
|
||||
using BlockID = System.UInt16;
|
||||
using System;
|
||||
using MCGalaxy.Games;
|
||||
|
||||
namespace MCGalaxy.Commands.Fun {
|
||||
public sealed class CmdGun : WeaponCmd {
|
||||
public sealed class CmdGun : Command2 {
|
||||
public override string name { get { return "Gun"; } }
|
||||
protected override string Weapon { get { return "Gun"; } }
|
||||
public override string type { get { return CommandTypes.Other; } }
|
||||
public override bool museumUsable { get { return false; } }
|
||||
public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } }
|
||||
public override bool SuperUseable { get { return false; } }
|
||||
|
||||
protected override void OnActivated(Player p, byte yaw, byte pitch, BlockID block) {
|
||||
WeaponArgs args = new WeaponArgs();
|
||||
args.player = p;
|
||||
args.block = block;
|
||||
args.weaponType = (WeaponType)p.blockchangeObject;
|
||||
|
||||
args.start = MakePos(p);
|
||||
args.dir = DirUtils.GetDirVector(yaw, pitch);
|
||||
args.pos = args.PosAt(3);
|
||||
args.iterations = 4;
|
||||
|
||||
SchedulerTask task = new SchedulerTask(GunCallback, args, TimeSpan.Zero, true);
|
||||
p.CriticalTasks.Add(task);
|
||||
}
|
||||
|
||||
static void GunCallback(SchedulerTask task) {
|
||||
WeaponArgs args = (WeaponArgs)task.State;
|
||||
if (args.moving) {
|
||||
args.moving = MoveGun(args);
|
||||
|
||||
// Laser gun persists for a short while
|
||||
if (!args.moving && args.weaponType == WeaponType.Laser)
|
||||
task.Delay = TimeSpan.FromMilliseconds(400);
|
||||
public override void Use(Player p, string message, CommandData data) {
|
||||
if (!p.level.Config.Guns) {
|
||||
p.Message("Guns cannot be used on this map!"); return;
|
||||
}
|
||||
if (p.weapon != null && message.Length == 0) {
|
||||
p.weapon.Disable();
|
||||
p.weapon = null;
|
||||
return;
|
||||
}
|
||||
|
||||
args.TeleportSourcePlayer();
|
||||
if (args.weaponType == WeaponType.Laser) {
|
||||
foreach (Vec3U16 pos in args.previous) {
|
||||
args.player.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
|
||||
}
|
||||
args.previous.Clear();
|
||||
} else if (args.previous.Count > 0) {
|
||||
Vec3U16 pos = args.previous[0];
|
||||
args.previous.RemoveAt(0);
|
||||
args.player.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
|
||||
}
|
||||
task.Repeating = args.previous.Count > 0;
|
||||
}
|
||||
|
||||
static bool MoveGun(WeaponArgs args) {
|
||||
while (true) {
|
||||
args.pos = args.PosAt(args.iterations);
|
||||
args.iterations++;
|
||||
Vec3U16 pos = args.pos;
|
||||
|
||||
BlockID cur = args.player.level.GetBlock(pos.X, pos.Y, pos.Z);
|
||||
if (cur == Block.Invalid) return false;
|
||||
if (cur != Block.Air && !args.allBlocks.Contains(pos) && HandlesHitBlock(args.player, cur, args.weaponType, pos, true))
|
||||
return false;
|
||||
|
||||
args.player.level.Blockchange(pos.X, pos.Y, pos.Z, args.block);
|
||||
args.previous.Add(pos);
|
||||
args.allBlocks.Add(pos);
|
||||
if (HitsPlayer(args, pos)) return false;
|
||||
|
||||
if (args.iterations > 12 && args.weaponType != WeaponType.Laser) {
|
||||
pos = args.previous[0];
|
||||
args.previous.RemoveAt(0);
|
||||
args.player.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
|
||||
}
|
||||
|
||||
if (args.weaponType != WeaponType.Laser) return true;
|
||||
}
|
||||
}
|
||||
|
||||
static Vec3U16 MakePos(Player p) { return (Vec3U16)p.Pos.BlockCoords; }
|
||||
|
||||
static bool HitsPlayer(WeaponArgs args, Vec3U16 pos) {
|
||||
Player pl = GetPlayer(args.player, pos, true);
|
||||
if (pl == null) return false;
|
||||
Gun gun = GetGun(p, message);
|
||||
if (gun == null) { Help(p); return; }
|
||||
|
||||
Player p = args.player;
|
||||
if (p.level.physics >= 3 && args.weaponType >= WeaponType.Explode) {
|
||||
pl.HandleDeath(Block.Cobblestone, "@p %Swas blown up by " + p.ColoredName, true);
|
||||
} else {
|
||||
pl.HandleDeath(Block.Cobblestone, "@p %Swas shot by " + p.ColoredName);
|
||||
}
|
||||
return true;
|
||||
p.weapon = gun;
|
||||
gun.Enable(p);
|
||||
}
|
||||
|
||||
static Gun GetGun(Player p, string mode) {
|
||||
if (mode.Length == 0) return new Gun();
|
||||
if (mode.CaselessEq("destroy")) return new PenetrativeGun();
|
||||
if (mode.CaselessEq("tp") || mode.CaselessEq("teleport")) return new TeleportGun();
|
||||
if (mode.CaselessEq("explode")) return new ExplosiveGun();
|
||||
if (mode.CaselessEq("laser")) return new LaserGun();
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
|
@ -87,7 +87,6 @@ namespace MCGalaxy.Commands.Fun {
|
||||
|
||||
class AimState {
|
||||
public Player player;
|
||||
public Position oldPos = default(Position);
|
||||
public List<Vec3U16> lastGlass = new List<Vec3U16>();
|
||||
public List<Vec3U16> glassCoords = new List<Vec3U16>();
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ namespace MCGalaxy.Commands.Moderation {
|
||||
int index = p.level.PosToInt(P.X, P.Y, P.Z);
|
||||
buffer.Add(index, P.Block);
|
||||
});
|
||||
buffer.Send(true);
|
||||
buffer.Flush();
|
||||
|
||||
if (op.found) {
|
||||
p.Message("Now highlighting past &b{0} %Sfor {1}",
|
||||
|
@ -77,7 +77,7 @@ namespace MCGalaxy.Commands.World {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
buffer.Send(true);
|
||||
buffer.Flush();
|
||||
}
|
||||
|
||||
static void FixLight(Player p, Level lvl, ref int totalFixed) {
|
||||
@ -117,7 +117,7 @@ namespace MCGalaxy.Commands.World {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
buffer.Send(true);
|
||||
buffer.Flush();
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
|
@ -31,7 +31,6 @@ namespace MCGalaxy.Commands.Building {
|
||||
p.staticCommands = false;
|
||||
p.deleteMode = false;
|
||||
p.ModeBlock = Block.Invalid;
|
||||
p.aiming = false;
|
||||
p.onTrain = false;
|
||||
p.isFlying = false;
|
||||
p.BrushName = "normal";
|
||||
@ -39,6 +38,7 @@ namespace MCGalaxy.Commands.Building {
|
||||
p.Transform = NoTransform.Instance;
|
||||
|
||||
p.level.blockqueue.RemoveAll(p);
|
||||
if (p.weapon != null) p.weapon.Disable();
|
||||
p.Message("Every toggle or action was aborted.");
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ namespace MCGalaxy.Games {
|
||||
if (!Running) return;
|
||||
|
||||
SetBoardOpening(Block.Air);
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
if (!Running) return;
|
||||
|
||||
BeginRound();
|
||||
@ -112,7 +112,7 @@ namespace MCGalaxy.Games {
|
||||
Cuboid(4, 4, maxZ - 4, maxX - 4, 4, maxZ - 4, Block.Air);
|
||||
Cuboid(4, 4, 4, 4, 4, maxZ - 4, Block.Air);
|
||||
Cuboid(maxX - 4, 4, 4, maxX - 4, 4, maxZ - 4, Block.Air);
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
}
|
||||
|
||||
void RemoveAllSquareBorders() {
|
||||
@ -123,7 +123,7 @@ namespace MCGalaxy.Games {
|
||||
for (int zz = 6 - 1; zz <= Map.Length - 6; zz += 3) {
|
||||
Cuboid(4, 4, zz, maxX - 4, 4, zz, Block.Air);
|
||||
}
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
}
|
||||
|
||||
void RemoveSquares() {
|
||||
@ -142,19 +142,19 @@ namespace MCGalaxy.Games {
|
||||
void RemoveSquare(SquarePos pos) {
|
||||
ushort x1 = pos.X, x2 = (ushort)(pos.X + 1), z1 = pos.Z, z2 = (ushort)(pos.Z + 1);
|
||||
Cuboid(x1, 4, z1, x2, 4, z2, Block.Yellow);
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
|
||||
Thread.Sleep(Interval);
|
||||
Cuboid(x1, 4, z1, x2, 4, z2, Block.Orange);
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
|
||||
Thread.Sleep(Interval);
|
||||
Cuboid(x1, 4, z1, x2, 4, z2, Block.Red);
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
|
||||
Thread.Sleep(Interval);
|
||||
Cuboid(x1, 4, z1, x2, 4, z2, Block.Air);
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
|
||||
// Remove glass borders, if neighbouring squares were previously removed
|
||||
bool airMaxX = false, airMinZ = false, airMaxZ = false, airMinX = false;
|
||||
|
@ -128,13 +128,13 @@ namespace MCGalaxy.Games {
|
||||
squaresLeft.Add(new SquarePos(xx, zz));
|
||||
}
|
||||
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
}
|
||||
|
||||
void SetBoardOpening(BlockID block) {
|
||||
int midX = Map.Width / 2, midY = Map.Height / 2, midZ = Map.Length / 2;
|
||||
Cuboid(midX - 1, midY, midZ - 1, midX, midY, midZ, block);
|
||||
bulk.Send(true);
|
||||
bulk.Flush();
|
||||
}
|
||||
|
||||
void Cuboid(int x1, int y1, int z1, int x2, int y2, int z2, BlockID block) {
|
||||
|
177
MCGalaxy/Games/Weapons/Guns.cs
Normal file
177
MCGalaxy/Games/Weapons/Guns.cs
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
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 MCGalaxy.Tasks;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
/// <summary> Represents a gun weapon which dies when it hits a block or a player. </summary>
|
||||
/// <remarks> Fires in a straight line from where playing is looking. </remarks>
|
||||
public class Gun : Weapon {
|
||||
public override string Name { get { return "Gun"; } }
|
||||
|
||||
protected override void OnActivated(byte yaw, byte pitch, BlockID block) {
|
||||
AmmunitionData args = new AmmunitionData();
|
||||
args.block = block;
|
||||
|
||||
args.start = (Vec3U16)p.Pos.BlockCoords;
|
||||
args.dir = DirUtils.GetDirVector(yaw, pitch);
|
||||
args.pos = args.PosAt(3);
|
||||
args.iterations = 4;
|
||||
|
||||
SchedulerTask task = new SchedulerTask(GunCallback, args, TimeSpan.Zero, true);
|
||||
p.CriticalTasks.Add(task);
|
||||
}
|
||||
|
||||
protected virtual bool OnHitBlock(AmmunitionData args, Vec3U16 pos, BlockID block) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual void OnHitPlayer(AmmunitionData args, Player pl) {
|
||||
pl.HandleDeath(Block.Cobblestone, "@p %Swas shot by " + p.ColoredName);
|
||||
}
|
||||
|
||||
protected virtual bool TickMove(AmmunitionData args) {
|
||||
if (args.iterations > 12) {
|
||||
Vec3U16 pos = args.visible[0];
|
||||
args.visible.RemoveAt(0);
|
||||
p.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual bool TickRevert(SchedulerTask task) {
|
||||
AmmunitionData args = (AmmunitionData)task.State;
|
||||
|
||||
if (args.visible.Count > 0) {
|
||||
Vec3U16 pos = args.visible[0];
|
||||
args.visible.RemoveAt(0);
|
||||
p.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
|
||||
}
|
||||
return args.visible.Count > 0;
|
||||
}
|
||||
|
||||
void GunCallback(SchedulerTask task) {
|
||||
AmmunitionData args = (AmmunitionData)task.State;
|
||||
if (args.moving) {
|
||||
args.moving = TickGun(args);
|
||||
} else {
|
||||
task.Repeating = TickRevert(task);
|
||||
}
|
||||
}
|
||||
|
||||
bool TickGun(AmmunitionData args) {
|
||||
while (true) {
|
||||
args.pos = args.PosAt(args.iterations);
|
||||
args.iterations++;
|
||||
Vec3U16 pos = args.pos;
|
||||
|
||||
BlockID cur = p.level.GetBlock(pos.X, pos.Y, pos.Z);
|
||||
if (cur == Block.Invalid) return false;
|
||||
if (cur != Block.Air && !args.all.Contains(pos) && OnHitBlock(args, pos, cur))
|
||||
return false;
|
||||
|
||||
p.level.Blockchange(pos.X, pos.Y, pos.Z, args.block);
|
||||
args.visible.Add(pos);
|
||||
args.all.Add(pos);
|
||||
|
||||
Player pl = PlayerAt(p, pos, true);
|
||||
if (pl != null) { OnHitPlayer(args, pl); return false; }
|
||||
if (TickMove(args)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PenetrativeGun : Gun {
|
||||
public override string Name { get { return "Penetrative gun"; } }
|
||||
|
||||
protected override bool OnHitBlock(AmmunitionData args, Vec3U16 pos, BlockID block) {
|
||||
if (p.level.physics < 2 || block == Block.Glass) return true;
|
||||
// Penetrative gun goes through blocks lava can go through
|
||||
return !p.level.Props[block].LavaKills;
|
||||
}
|
||||
}
|
||||
|
||||
public class ExplosiveGun : Gun {
|
||||
public override string Name { get { return "Explosive gun"; } }
|
||||
|
||||
protected override bool OnHitBlock(AmmunitionData args, Vec3U16 pos, BlockID block) {
|
||||
if (p.level.physics >= 3 && block != Block.Glass) {
|
||||
p.level.MakeExplosion(pos.X, pos.Y, pos.Z, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHitPlayer(AmmunitionData args, Player pl) {
|
||||
if (pl.level.physics >= 3) {
|
||||
pl.HandleDeath(Block.Cobblestone, "@p %Swas blown up by " + p.ColoredName, true);
|
||||
} else {
|
||||
base.OnHitPlayer(args, pl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LaserGun : ExplosiveGun {
|
||||
public override string Name { get { return "Laser"; } }
|
||||
|
||||
protected override bool TickMove(AmmunitionData args) {
|
||||
// laser immediately strikes target
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override bool TickRevert(SchedulerTask task) {
|
||||
AmmunitionData args = (AmmunitionData)task.State;
|
||||
|
||||
if (args.all.Count > 0) {
|
||||
// laser persists for a short while
|
||||
task.Delay = TimeSpan.FromMilliseconds(400);
|
||||
args.all.Clear();
|
||||
} else {
|
||||
foreach (Vec3U16 pos in args.visible) {
|
||||
p.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true);
|
||||
}
|
||||
args.visible.Clear();
|
||||
}
|
||||
return args.visible.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class TeleportGun : Gun {
|
||||
public override string Name { get { return "Teleporter gun"; } }
|
||||
|
||||
void DoTeleport(AmmunitionData args) {
|
||||
int i = args.visible.Count - 3;
|
||||
if (i >= 0 && i < args.visible.Count) {
|
||||
Vec3U16 coords = args.visible[i];
|
||||
Position pos = new Position(coords.X * 32, coords.Y * 32 + 32, coords.Z * 32);
|
||||
p.SendPos(Entities.SelfID, pos, p.Rot);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnHitPlayer(AmmunitionData args, Player pl) {
|
||||
DoTeleport(args);
|
||||
}
|
||||
|
||||
protected override bool OnHitBlock(AmmunitionData args, Vec3U16 pos, BlockID block) {
|
||||
DoTeleport(args);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
195
MCGalaxy/Games/Weapons/Weapon.cs
Normal file
195
MCGalaxy/Games/Weapons/Weapon.cs
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
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.Commands;
|
||||
using MCGalaxy.Events.PlayerEvents;
|
||||
using MCGalaxy.Maths;
|
||||
using MCGalaxy.Tasks;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Games {
|
||||
|
||||
/// <summary> Represents a weapon which can interact with blocks or players until it dies. </summary>
|
||||
/// <remarks> Activated by clicking through either PlayerClick or a glass box around the player. </remarks>
|
||||
public abstract class Weapon {
|
||||
|
||||
public abstract string Name { get; }
|
||||
static bool hookedEvents;
|
||||
|
||||
protected Player p;
|
||||
AimBox aimer;
|
||||
|
||||
public void Enable(Player p) {
|
||||
if (!hookedEvents) {
|
||||
OnPlayerClickEvent.Register(PlayerClickCallback, Priority.Low);
|
||||
hookedEvents = true;
|
||||
}
|
||||
this.p = p;
|
||||
p.ClearBlockchange();
|
||||
|
||||
if (p.Supports(CpeExt.PlayerClick)) {
|
||||
p.Message(Name + " engaged, click to fire at will");
|
||||
} else {
|
||||
p.Blockchange += BlockClickCallback;
|
||||
p.Message(Name + " engaged, fire at will");
|
||||
aimer = new AimBox();
|
||||
aimer.Hook(p);
|
||||
}
|
||||
}
|
||||
|
||||
public void Disable() {
|
||||
p.aiming = false;
|
||||
p.ClearBlockchange();
|
||||
p.Message(Name + " disabled");
|
||||
}
|
||||
|
||||
protected abstract void OnActivated(byte yaw, byte pitch, BlockID block);
|
||||
|
||||
|
||||
static void BlockClickCallback(Player p, ushort x, ushort y, ushort z, BlockID block) {
|
||||
Weapon weapon = p.weapon;
|
||||
if (weapon == null) return;
|
||||
|
||||
p.RevertBlock(x, y, z);
|
||||
// defer to player click handler
|
||||
if (weapon.aimer == null) return;
|
||||
|
||||
if (!p.level.Config.Guns) { weapon.Disable(); return; }
|
||||
if (!CommandParser.IsBlockAllowed(p, "use", block)) return;
|
||||
|
||||
weapon.OnActivated(p.Rot.RotY, p.Rot.HeadX, block);
|
||||
}
|
||||
|
||||
static void PlayerClickCallback(Player p, MouseButton btn, MouseAction action,
|
||||
ushort yaw, ushort pitch, byte entity,
|
||||
ushort x, ushort y, ushort z, TargetBlockFace face) {
|
||||
Weapon weapon = p.weapon;
|
||||
if (weapon == null || action != MouseAction.Pressed) return;
|
||||
|
||||
if (!(btn == MouseButton.Left || btn == MouseButton.Right)) return;
|
||||
if (!p.level.Config.Guns) { weapon.Disable(); return; }
|
||||
|
||||
BlockID held = p.RawHeldBlock;
|
||||
if (!CommandParser.IsBlockAllowed(p, "use", held)) return;
|
||||
weapon.OnActivated((byte)(yaw >> 8), (byte)(pitch >> 8), held);
|
||||
}
|
||||
|
||||
protected static Player PlayerAt(Player p, Vec3U16 pos, bool skipSelf) {
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in players) {
|
||||
if (pl.level != p.level) continue;
|
||||
if (p == pl && skipSelf) continue;
|
||||
|
||||
if (Math.Abs(pl.Pos.BlockX - pos.X) <= 1
|
||||
&& Math.Abs(pl.Pos.BlockY - pos.Y) <= 1
|
||||
&& Math.Abs(pl.Pos.BlockZ - pos.Z) <= 1)
|
||||
{
|
||||
return pl;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class AmmunitionData {
|
||||
public BlockID block;
|
||||
public Vec3U16 pos, start;
|
||||
public Vec3F32 dir;
|
||||
public bool moving = true;
|
||||
|
||||
// positions of all currently visible "trailing" blocks
|
||||
public List<Vec3U16> visible = new List<Vec3U16>();
|
||||
// position of all blocks this ammunition has touched/gone through
|
||||
public List<Vec3U16> all = new List<Vec3U16>();
|
||||
public int iterations;
|
||||
|
||||
public Vec3U16 PosAt(int i) {
|
||||
Vec3U16 target;
|
||||
target.X = (ushort)Math.Round(start.X + (double)(dir.X * i));
|
||||
target.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * i));
|
||||
target.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * i));
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Manages the glass box around the player. Adjusts based on where player is looking. </summary>
|
||||
internal sealed class AimBox {
|
||||
|
||||
Player player;
|
||||
List<Vec3U16> lastGlass = new List<Vec3U16>();
|
||||
List<Vec3U16> curGlass = new List<Vec3U16>();
|
||||
|
||||
public void Hook(Player p) {
|
||||
player = p;
|
||||
SchedulerTask task = new SchedulerTask(AimCallback, null, TimeSpan.Zero, true);
|
||||
p.CriticalTasks.Add(task);
|
||||
}
|
||||
|
||||
void AimCallback(SchedulerTask task) {
|
||||
Player p = player;
|
||||
if (p.aiming) { Update(); return; }
|
||||
|
||||
foreach (Vec3U16 pos in lastGlass) {
|
||||
if (!p.level.IsValidPos(pos)) continue;
|
||||
p.RevertBlock(pos.X, pos.Y, pos.Z);
|
||||
}
|
||||
task.Repeating = false;
|
||||
}
|
||||
|
||||
void Update() {
|
||||
Player p = player;
|
||||
Vec3F32 dir = DirUtils.GetDirVector(p.Rot.RotY, p.Rot.HeadX);
|
||||
ushort x = (ushort)Math.Round(p.Pos.BlockX + dir.X * 3);
|
||||
ushort y = (ushort)Math.Round(p.Pos.BlockY + dir.Y * 3);
|
||||
ushort z = (ushort)Math.Round(p.Pos.BlockZ + dir.Z * 3);
|
||||
|
||||
int dx = Math.Sign(dir.X) >= 0 ? 1 : -1, dz = Math.Sign(dir.Z) >= 0 ? 1 : -1;
|
||||
Check(p.level, x, y, z );
|
||||
Check(p.level, x + dx, y, z );
|
||||
Check(p.level, x, y, z + dz);
|
||||
Check(p.level, x + dx, y, z + dz);
|
||||
|
||||
// Revert all glass blocks now not in the ray from the player's direction
|
||||
for (int i = 0; i < lastGlass.Count; i++) {
|
||||
Vec3U16 pos = lastGlass[i];
|
||||
if (curGlass.Contains(pos)) continue;
|
||||
|
||||
if (p.level.IsValidPos(pos))
|
||||
p.RevertBlock(pos.X, pos.Y, pos.Z);
|
||||
lastGlass.RemoveAt(i); i--;
|
||||
}
|
||||
|
||||
// Place the new glass blocks that are in the ray from the player's direction
|
||||
foreach (Vec3U16 pos in curGlass) {
|
||||
if (lastGlass.Contains(pos)) continue;
|
||||
lastGlass.Add(pos);
|
||||
p.SendBlockchange(pos.X, pos.Y, pos.Z, Block.Glass);
|
||||
}
|
||||
curGlass.Clear();
|
||||
}
|
||||
|
||||
void Check(Level lvl, int x, int y, int z) {
|
||||
Vec3U16 pos = new Vec3U16((ushort)x, (ushort)(y - 1), (ushort)z);
|
||||
if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos);
|
||||
|
||||
pos.Y++;
|
||||
if (lvl.IsAirAt(pos.X, pos.Y, pos.Z)) curGlass.Add(pos);
|
||||
}
|
||||
}
|
||||
}
|
@ -80,7 +80,7 @@ namespace MCGalaxy {
|
||||
BlockID block = (BlockID)(flags & blockMask);
|
||||
bulkSender.Add(index, block);
|
||||
}
|
||||
bulkSender.Send(true);
|
||||
bulkSender.Flush();
|
||||
RemoveRange(0, count);
|
||||
} catch (Exception e) {
|
||||
Logger.LogError(e);
|
||||
|
@ -198,7 +198,7 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
if (bulkSender != null)
|
||||
bulkSender.Send(true);
|
||||
bulkSender.Flush();
|
||||
ListUpdate.Clear(); listUpdateExists.Clear();
|
||||
}
|
||||
|
||||
|
@ -192,9 +192,8 @@ namespace MCGalaxy {
|
||||
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
foreach (Player pl in players) {
|
||||
if (pl.level != lvl || !pl.aiming) continue;
|
||||
pl.aiming = false;
|
||||
pl.ClearBlockchange();
|
||||
if (pl.level != lvl || pl.weapon == null) continue;
|
||||
pl.weapon.Disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,6 +505,8 @@
|
||||
<Compile Include="Games\TntWars\TWGame.Round.cs" />
|
||||
<Compile Include="Games\TntWars\TWGame.cs" />
|
||||
<Compile Include="Games\TntWars\TWConfig.cs" />
|
||||
<Compile Include="Games\Weapons\Weapon.cs" />
|
||||
<Compile Include="Games\Weapons\Guns.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZSGame.DB.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZSGame.Round.cs" />
|
||||
<Compile Include="Games\ZombieSurvival\ZSGame.cs" />
|
||||
@ -718,6 +720,7 @@
|
||||
<Folder Include="Commands\Maintenance" />
|
||||
<Folder Include="Config\Permissions" />
|
||||
<Folder Include="Database\Stats" />
|
||||
<Folder Include="Games\Weapons" />
|
||||
<Folder Include="Games\RoundsGame" />
|
||||
<Folder Include="Generator\Realistic" />
|
||||
<Folder Include="Network\Heartbeat" />
|
||||
|
@ -39,13 +39,12 @@ namespace MCGalaxy.Network {
|
||||
/// <summary> Constructs a bulk sender that will only send block changes to that player. </summary>
|
||||
public BufferedBlockSender(Player player) {
|
||||
this.player = player;
|
||||
this.level = player.level;
|
||||
this.level = player.level;
|
||||
}
|
||||
|
||||
/// <summary> Adds a block change, and potentially sends block change packets if
|
||||
/// number of buffered block changes has reached the limit. </summary>
|
||||
/// <returns> Whether block change packets were actually sent. </returns>
|
||||
public bool Add(int index, BlockID block) {
|
||||
/// <summary> Adds a block change to list of buffered changes. </summary>
|
||||
/// <remarks> When buffer limit is reached, calls Flush(), resetting buffered list. </remarks>
|
||||
public void Add(int index, BlockID block) {
|
||||
indices[count] = index;
|
||||
if (Block.IsPhysicsType(block)) {
|
||||
blocks[count] = Block.Convert(block);
|
||||
@ -54,20 +53,16 @@ namespace MCGalaxy.Network {
|
||||
}
|
||||
|
||||
count++;
|
||||
return Send(false);
|
||||
if (count == 256) Flush();
|
||||
}
|
||||
|
||||
/// <summary> Sends the block change packets if either 'force' is true,
|
||||
/// or the number of buffered block changes has reached the limit. </summary>
|
||||
/// <returns> Whether block change packets were actually sent. </returns>
|
||||
public bool Send(bool force) {
|
||||
if (count > 0 && (force || count == 256)) {
|
||||
if (player != null) SendPlayer();
|
||||
else SendLevel();
|
||||
count = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
/// <summary> Sends buffered block change packets to target player(s). </summary>
|
||||
public void Flush() {
|
||||
if (count == 0) return;
|
||||
|
||||
if (player != null) SendPlayer();
|
||||
else SendLevel();
|
||||
count = 0;
|
||||
}
|
||||
|
||||
void SendLevel() {
|
||||
|
@ -126,6 +126,7 @@ namespace MCGalaxy {
|
||||
public VolatileArray<SchedulerTask> CriticalTasks = new VolatileArray<SchedulerTask>();
|
||||
|
||||
public bool aiming;
|
||||
public Weapon weapon;
|
||||
public bool isFlying;
|
||||
|
||||
public bool joker;
|
||||
|
@ -239,7 +239,7 @@ namespace MCGalaxy {
|
||||
LastAction = DateTime.UtcNow;
|
||||
IsAfk = false;
|
||||
isFlying = false;
|
||||
aiming = false;
|
||||
if (weapon != null) weapon.Disable();
|
||||
|
||||
if (chatMsg != null) chatMsg = Colors.Escape(chatMsg);
|
||||
discMsg = Colors.Escape(discMsg);
|
||||
|
Loading…
x
Reference in New Issue
Block a user