Progress on tutorial, misc bugfixes

This commit is contained in:
Regalis
2015-08-20 00:42:24 +03:00
parent e19ac600ff
commit 8c559f716f
19 changed files with 356 additions and 85 deletions
@@ -43,7 +43,7 @@ namespace Subsurface
steeringManager = new SteeringManager(this); steeringManager = new SteeringManager(this);
} }
public virtual void SelectTarget(IDamageable target) { } public virtual void SelectTarget(AITarget target) { }
public virtual void Update(float deltaTime) { } public virtual void Update(float deltaTime) { }
@@ -82,11 +82,10 @@ namespace Subsurface
state = AiState.None; state = AiState.None;
} }
public override void SelectTarget(IDamageable target) public override void SelectTarget(AITarget target)
{ {
targetEntity = target; selectedAiTarget = target;
selectedAiTarget = target.AiTarget; selectedTargetMemory = FindTargetMemory(target);
selectedTargetMemory = FindTargetMemory(target.AiTarget);
targetValue = 100.0f; targetValue = 100.0f;
} }
@@ -31,7 +31,11 @@ namespace Subsurface
public float StunTimer public float StunTimer
{ {
get { return stunTimer; } get { return stunTimer; }
set { stunTimer = value; } set
{
if (float.IsNaN(value) || float.IsInfinity(value)) return;
stunTimer = value;
}
} }
public AnimController(Character character, XElement element) public AnimController(Character character, XElement element)
+19 -8
View File
@@ -1024,6 +1024,10 @@ namespace Subsurface
{ {
return; return;
} }
else if (type== NetworkEventType.NotMoving)
{
return;
}
//if (type == Networking.NetworkEventType.KeyHit) //if (type == Networking.NetworkEventType.KeyHit)
@@ -1057,11 +1061,11 @@ namespace Subsurface
message.Write(limb.body.Position.X); message.Write(limb.body.Position.X);
message.Write(limb.body.Position.Y); message.Write(limb.body.Position.Y);
message.Write(limb.body.LinearVelocity.X); //message.Write(limb.body.LinearVelocity.X);
message.Write(limb.body.LinearVelocity.Y); //message.Write(limb.body.LinearVelocity.Y);
message.Write(limb.body.Rotation); message.Write(limb.body.Rotation);
message.Write(limb.body.AngularVelocity); //message.WriteRangedSingle(MathHelper.Clamp(limb.body.AngularVelocity, -10.0f, 10.0f), -10.0f, 10.0f, 8);
i++; i++;
} }
@@ -1118,6 +1122,13 @@ namespace Subsurface
} }
return; return;
} }
else if (type == NetworkEventType.NotMoving)
{
AnimController.TargetMovement = Vector2.Zero;
actionKeyDown.State = false;
secondaryKeyDown.State = false;
return;
}
bool actionKeyState = false; bool actionKeyState = false;
bool secondaryKeyState = false; bool secondaryKeyState = false;
@@ -1176,11 +1187,11 @@ namespace Subsurface
pos.X = message.ReadFloat(); pos.X = message.ReadFloat();
pos.Y = message.ReadFloat(); pos.Y = message.ReadFloat();
vel.X = message.ReadFloat(); //vel.X = message.ReadFloat();
vel.Y = message.ReadFloat(); //vel.Y = message.ReadFloat();
rotation = message.ReadFloat(); rotation = message.ReadFloat();
angularVel = message.ReadFloat(); //angularVel = message.ReadFloat();
} }
catch catch
{ {
@@ -1189,10 +1200,10 @@ namespace Subsurface
if (limb.body != null) if (limb.body != null)
{ {
limb.body.TargetVelocity = vel; limb.body.TargetVelocity = limb.body.LinearVelocity;
limb.body.TargetPosition = pos;// +vel * (float)(deltaTime / 60.0); limb.body.TargetPosition = pos;// +vel * (float)(deltaTime / 60.0);
limb.body.TargetRotation = rotation;// +angularVel * (float)(deltaTime / 60.0); limb.body.TargetRotation = rotation;// +angularVel * (float)(deltaTime / 60.0);
limb.body.TargetAngularVelocity = angularVel; limb.body.TargetAngularVelocity = limb.body.AngularVelocity;
} }
} }
@@ -3,6 +3,7 @@ using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
using FarseerPhysics; using FarseerPhysics;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Subsurface.Items.Components;
namespace Subsurface namespace Subsurface
{ {
@@ -542,7 +543,7 @@ namespace Subsurface
void UpdateClimbing() void UpdateClimbing()
{ {
if (character.SelectedConstruction == null) if (character.SelectedConstruction == null || character.SelectedConstruction.GetComponent<Ladder>()==null)
{ {
Anim = Animation.None; Anim = Animation.None;
return; return;
@@ -623,7 +624,12 @@ namespace Subsurface
torso.body.ApplyForce(climbForce * 40.0f * torso.Mass); torso.body.ApplyForce(climbForce * 40.0f * torso.Mass);
head.body.SmoothRotate(0.0f); head.body.SmoothRotate(0.0f);
Rectangle trigger = character.SelectedConstruction.Prefab.Triggers.First(); Rectangle trigger = character.SelectedConstruction.Prefab.Triggers.FirstOrDefault();
if (trigger == null)
{
character.SelectedConstruction = null;
return;
}
trigger = character.SelectedConstruction.TransformTrigger(trigger); trigger = character.SelectedConstruction.TransformTrigger(trigger);
//stop climbing if: //stop climbing if:
+3 -3
View File
@@ -472,7 +472,7 @@ namespace Subsurface
inWater = false; inWater = false;
headInWater = false; headInWater = false;
if (currentHull.Volume>currentHull.FullVolume*0.95f || ConvertUnits.ToSimUnits(currentHull.Surface)-floorY> HeadPosition*0.95f) if (currentHull.Volume > currentHull.FullVolume * 0.95f || ConvertUnits.ToSimUnits(currentHull.Surface) - floorY > HeadPosition * 0.95f)
inWater = true; inWater = true;
} }
@@ -562,7 +562,7 @@ namespace Subsurface
private void UpdateNetplayerPosition() private void UpdateNetplayerPosition()
{ {
Limb refLimb = GetLimb(LimbType.Torso); Limb refLimb = GetLimb(LimbType.Torso);
if (refLimb== null) refLimb = GetLimb(LimbType.Head); if (refLimb == null) refLimb = GetLimb(LimbType.Head);
if (refLimb.body.TargetPosition == Vector2.Zero) return; if (refLimb.body.TargetPosition == Vector2.Zero) return;
@@ -603,7 +603,7 @@ namespace Subsurface
if (resetAll) if (resetAll)
{ {
System.Diagnostics.Debug.WriteLine("resetall"); System.Diagnostics.Debug.WriteLine("reset ragdoll limb positions");
foreach (Limb limb in limbs) foreach (Limb limb in limbs)
{ {
@@ -22,6 +22,8 @@ namespace Subsurface
Game1.GameSession.StartShift(TimeSpan.Zero, "tutorial"); Game1.GameSession.StartShift(TimeSpan.Zero, "tutorial");
Game1.GameSession.taskManager.Tasks.Clear();
Game1.GameScreen.Select(); Game1.GameScreen.Select();
} }
@@ -184,7 +186,7 @@ namespace Subsurface
+ " going into the to the power connection - that's why the monitor isn't working." + " going into the to the power connection - that's why the monitor isn't working."
+ " You should find a piece of wire to connect it. Try searching some of the cabinets scattered around the sub."); + " You should find a piece of wire to connect it. Try searching some of the cabinets scattered around the sub.");
while (Character.Controlled.Inventory.items.FirstOrDefault(i => i!=null && i.GetComponent<Wire>()!=null)==null) while (!HasItem("Wire"))
{ {
yield return Status.Running; yield return Status.Running;
} }
@@ -280,32 +282,159 @@ namespace Subsurface
var moloch = new Character("Content/Characters/Moloch/moloch.xml", steering.Item.SimPosition + Vector2.UnitX * 15.0f); var moloch = new Character("Content/Characters/Moloch/moloch.xml", steering.Item.SimPosition + Vector2.UnitX * 15.0f);
moloch.PlaySound(AIController.AiState.Attack); moloch.PlaySound(AIController.AiState.Attack);
//moloch.AIController.
infoBox = CreateInfoFrame("Uh-oh... Something enormous just appeared on the radar."); infoBox = CreateInfoFrame("Uh-oh... Something enormous just appeared on the radar.");
Structure window = null; List<Structure> windows = new List<Structure>();
foreach (Structure s in Structure.wallList) foreach (Structure s in Structure.wallList)
{ {
if (s.CastShadow) continue; if (s.CastShadow || !s.HasBody) continue;
if (window == null || s.Rect.Right > window.Rect.Right) window = s; if (s.Rect.Right > steering.Item.Position.X) windows.Add(s);
} }
bool broken = false; bool broken = false;
do do
{ {
moloch.AIController.SelectTarget(steering.Item); moloch.AIController.SelectTarget(steering.Item.CurrentHull.AiTarget);
for (int i = 0; i < window.SectionCount; i++) Vector2 steeringDir = windows[0].Position - moloch.Position;
if (steeringDir != Vector2.Zero) steeringDir = Vector2.Normalize(steeringDir);
foreach (Limb limb in moloch.AnimController.limbs)
{ {
if (!window.SectionHasHole(i)) continue; limb.body.LinearVelocity = new Vector2(limb.LinearVelocity.X, limb.LinearVelocity.Y + steeringDir.Y*0.01f);
broken = true;
break;
} }
moloch.AIController.Steering = steeringDir;
foreach (Structure window in windows)
{
for (int i = 0; i < window.SectionCount; i++)
{
if (!window.SectionHasHole(i)) continue;
broken = true;
break;
}
if (broken) break;
}
yield return new WaitForSeconds(1.0f); yield return new WaitForSeconds(1.0f);
} while (!broken); } while (!broken);
yield return new WaitForSeconds(1.0f);
var capacitor1 = Item.itemList.Find(i => i.HasTag("capacitor1")).GetComponent<PowerContainer>();
var capacitor2 = Item.itemList.Find(i => i.HasTag("capacitor1")).GetComponent<PowerContainer>();
CoroutineManager.StartCoroutine(KeepEnemyAway(moloch, new PowerContainer[] { capacitor1, capacitor2 }));
infoBox = CreateInfoFrame("The hull has been breached! Close all the doors to the command room to stop the water from flooding the entire sub!");
Door commandDoor1 = Item.itemList.Find(i => i.HasTag("commanddoor1")).GetComponent<Door>();
Door commandDoor2 = Item.itemList.Find(i => i.HasTag("commanddoor2")).GetComponent<Door>();
Door commandDoor3 = Item.itemList.Find(i => i.HasTag("commanddoor3")).GetComponent<Door>();
while (commandDoor1.IsOpen && (commandDoor2.IsOpen || commandDoor3.IsOpen))
{
yield return Status.Running;
}
infoBox = CreateInfoFrame("Great! You should find yourself an diving mask or a diving suit, in case the creature causes more damage. "+
"There are some in the room next to the airlock.");
while (!HasItem("Diving Mask") && !HasItem("Diving Suit"))
{
yield return Status.Running;
}
if (HasItem("Diving Mask"))
{
infoBox = CreateInfoFrame("The diving mask will let you breathe underwater, but it won't protect from the water pressure outside the sub. "+
"It should be fine for the situation at hand, but you still need to find an oxygen tank and drag it into the same slot as the mask." +
"You should grab one or two.");
}
else if (HasItem("Diving Suit"))
{
infoBox = CreateInfoFrame("In addition to letting you breathe underwater, the suit will protect you from the water pressure outside the sub " +
"(unlike the diving mask). However, you still need to drag an oxygen tank into the same slot as the suit to supply oxygen. "+
"You should grab one or two.");
}
while (!HasItem("Oxygen Tank"))
{
yield return Status.Running;
}
yield return new WaitForSeconds(5.0f);
infoBox = CreateInfoFrame("Now it's time to stop the creature attacking the submarine. Head to the railgun room at the upper right corner of the sub.");
var railGun = Item.itemList.Find(i => i.GetComponent<Turret>()!=null);
while (Vector2.Distance(Character.Controlled.Position, railGun.Position)>500)
{
yield return new WaitForSeconds(1.0f);
}
infoBox = CreateInfoFrame("The railgun requires a large power surge to fire. The reactor can't provide a surge large enough, so we need to use the "
+" supercapacitors in the railgun room. The capacitors need to be charged first; select them and crank up the recharge rate.");
while (capacitor1.RechargeSpeed<0.5f && capacitor2.RechargeSpeed<0.5f)
{
yield return new WaitForSeconds(1.0f);
}
infoBox = CreateInfoFrame("The capacitors consume large amounts of power when they're being charged at a high rate. "+
"Be cautious to overload the electrical grid or the reactor. They also take some time to recharge, so now is a good "+
"time to head to the room below to load some shells into the railgun.");
var loader = Item.itemList.Find(i => i.Name == "Railgun Loader").GetComponent<ItemContainer>();
while (Math.Abs(Character.Controlled.Position.Y - loader.Item.Position.Y)>50)
{
yield return Status.Running;
}
infoBox = CreateInfoFrame("Grab one of the shells. You can load it by selecting the railgun loader and dragging the shell to. "
+"one of the free slots.");
while (loader.Item.ContainedItems.FirstOrDefault(i => i != null) != null)
{
capacitor1.Charge += 1.0f;
capacitor2.Charge += 1.0f;
yield return Status.Running;
}
yield return Status.Success;
}
private bool HasItem(string itemName)
{
if (Character.Controlled == null) return false;
return Character.Controlled.Inventory.items.FirstOrDefault(i => i != null && i.Name == itemName)!=null;
}
/// <summary>
/// keeps the enemy away from the sub until the capacitors are loaded
/// </summary>
private IEnumerable<object> KeepEnemyAway(Character enemy, PowerContainer[] capacitors)
{
do
{
Vector2 targetPos = Character.Controlled.Position + new Vector2(0.0f, 3000.0f);
Vector2 steering = targetPos - enemy.Position;
if (steering != Vector2.Zero) steering = Vector2.Normalize(steering);
enemy.AIController.Steering = steering*2.0f;
yield return Status.Running;
} while (capacitors.FirstOrDefault(c => c.Charge > 0.4f) == null);
yield return Status.Success; yield return Status.Success;
} }
+4 -1
View File
@@ -92,8 +92,11 @@ namespace Subsurface.Items.Components
newText = message.ReadString(); newText = message.ReadString();
} }
catch catch (Exception e)
{ {
#if DEBUG
DebugConsole.ThrowError("invalid network message", e);
#endif
return; return;
} }
@@ -22,8 +22,9 @@ namespace Subsurface.Items.Components
get { return flowPercentage; } get { return flowPercentage; }
set set
{ {
if (float.IsNaN(flowPercentage)) return; if (!MathUtils.IsValid(flowPercentage)) return;
flowPercentage = MathHelper.Clamp(value,-100.0f,100.0f); flowPercentage = MathHelper.Clamp(value,-100.0f,100.0f);
flowPercentage = MathUtils.Round(flowPercentage, 1.0f);
} }
} }
@@ -117,14 +118,14 @@ namespace Subsurface.Items.Components
spriteBatch.DrawString(GUI.Font, "Flow percentage: " + (int)flowPercentage + " %", new Vector2(x + 20, y + 80), Color.White); spriteBatch.DrawString(GUI.Font, "Flow percentage: " + (int)flowPercentage + " %", new Vector2(x + 20, y + 80), Color.White);
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 200, y + 70, 40, 40), "+", true)) if (GUI.DrawButton(spriteBatch, new Rectangle(x + 200, y + 70, 40, 40), "+", false))
{ {
FlowPercentage += 1.0f; FlowPercentage += 10.0f;
item.NewComponentEvent(this, true); item.NewComponentEvent(this, true);
} }
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 250, y + 70, 40, 40), "-", true)) if (GUI.DrawButton(spriteBatch, new Rectangle(x + 250, y + 70, 40, 40), "-", false))
{ {
FlowPercentage -= 1.0f; FlowPercentage -= 10.0f;
item.NewComponentEvent(this, true); item.NewComponentEvent(this, true);
} }
@@ -166,7 +167,7 @@ namespace Subsurface.Items.Components
public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message) public override void FillNetworkData(Networking.NetworkEventType type, Lidgren.Network.NetOutgoingMessage message)
{ {
message.Write(flowPercentage); message.Write(Convert.ToByte(flowPercentage+100));
message.Write(isActive); message.Write(isActive);
} }
@@ -177,11 +178,17 @@ namespace Subsurface.Items.Components
try try
{ {
newFlow = message.ReadFloat(); newFlow = (float)(message.ReadByte()-100);
newActive = message.ReadBoolean(); newActive = message.ReadBoolean();
} }
catch { return; } catch (Exception e)
{
#if DEBUG
DebugConsole.ThrowError("invalid network message", e);
#endif
return;
}
FlowPercentage = newFlow; FlowPercentage = newFlow;
isActive = newActive; isActive = newActive;
@@ -68,19 +68,31 @@ namespace Subsurface.Items.Components
public float FissionRate public float FissionRate
{ {
get { return fissionRate; } get { return fissionRate; }
set { fissionRate = MathHelper.Clamp(value, 0.0f, 100.0f); } set
{
if (!MathUtils.IsValid(value)) return;
fissionRate = MathHelper.Clamp(value, 0.0f, 100.0f);
}
} }
public float CoolingRate public float CoolingRate
{ {
get { return coolingRate; } get { return coolingRate; }
set { coolingRate = MathHelper.Clamp(value, 0.0f, 100.0f); } set
{
if (!MathUtils.IsValid(value)) return;
coolingRate = MathHelper.Clamp(value, 0.0f, 100.0f);
}
} }
public float Temperature public float Temperature
{ {
get { return temperature; } get { return temperature; }
set { temperature = MathHelper.Clamp(value, 0.0f, 10000.0f); } set
{
if (!MathUtils.IsValid(value)) return;
temperature = MathHelper.Clamp(value, 0.0f, 10000.0f);
}
} }
public bool IsRunning() public bool IsRunning()
@@ -100,6 +112,7 @@ namespace Subsurface.Items.Components
public float ShutDownTemp public float ShutDownTemp
{ {
get { return shutDownTemp; } get { return shutDownTemp; }
private set { shutDownTemp = MathHelper.Clamp(value, 0.0f, 10000.0f); }
} }
public Reactor(Item item, XElement element) public Reactor(Item item, XElement element)
@@ -334,12 +347,12 @@ namespace Subsurface.Items.Components
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 400, y + 180, 40, 40), "+", true)) if (GUI.DrawButton(spriteBatch, new Rectangle(x + 400, y + 180, 40, 40), "+", true))
{ {
valueChanged = true; valueChanged = true;
shutDownTemp += 100.0f; ShutDownTemp += 100.0f;
} }
if (GUI.DrawButton(spriteBatch, new Rectangle(x + 450, y + 180, 40, 40), "-", true)) if (GUI.DrawButton(spriteBatch, new Rectangle(x + 450, y + 180, 40, 40), "-", true))
{ {
valueChanged = true; valueChanged = true;
shutDownTemp -= 100.0f; ShutDownTemp -= 100.0f;
} }
if (valueChanged) if (valueChanged)
@@ -392,11 +405,11 @@ namespace Subsurface.Items.Components
public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message) public override void FillNetworkData(NetworkEventType type, NetOutgoingMessage message)
{ {
message.Write(autoTemp); message.Write(autoTemp);
message.Write(temperature); message.WriteRangedSingle(temperature, 0.0f, 10000.0f, 16);
message.Write(shutDownTemp); message.WriteRangedSingle(shutDownTemp, 0.0f, 10000.0f, 16);
message.Write(coolingRate); message.WriteRangedSingle(coolingRate, 0.0f, 100.0f, 8);
message.Write(fissionRate); message.WriteRangedSingle(fissionRate, 0.0f, 100.0f, 8);
} }
public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) public override void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
@@ -408,18 +421,24 @@ namespace Subsurface.Items.Components
try try
{ {
newAutoTemp = message.ReadBoolean(); newAutoTemp = message.ReadBoolean();
newTemperature = message.ReadFloat(); newTemperature = message.ReadRangedSingle(0.0f, 10000.0f, 16);
newShutDownTemp = message.ReadFloat(); newShutDownTemp = message.ReadRangedSingle(0.0f, 10000.0f, 16);
newCoolingRate = message.ReadFloat(); newCoolingRate = message.ReadRangedSingle(0.0f, 100.0f, 8);
newFissionRate = message.ReadFloat(); newFissionRate = message.ReadRangedSingle(0.0f, 100.0f, 8);
} }
catch { return; } catch (Exception e)
{
#if DEBUG
DebugConsole.ThrowError("invalid network message", e);
#endif
return;
}
autoTemp = newAutoTemp; autoTemp = newAutoTemp;
Temperature = newTemperature; Temperature = newTemperature;
shutDownTemp = newShutDownTemp; ShutDownTemp = newShutDownTemp;
CoolingRate = newCoolingRate; CoolingRate = newCoolingRate;
FissionRate = newFissionRate; FissionRate = newFissionRate;
@@ -48,10 +48,7 @@ namespace Subsurface.Items.Components
get { return targetVelocity;} get { return targetVelocity;}
set set
{ {
if (float.IsNaN(value.X) || float.IsNaN(value.Y)) if (!MathUtils.IsValid(value)) return;
{
return;
}
targetVelocity.X = MathHelper.Clamp(value.X, -100.0f, 100.0f); targetVelocity.X = MathHelper.Clamp(value.X, -100.0f, 100.0f);
targetVelocity.Y = MathHelper.Clamp(value.Y, -100.0f, 100.0f); targetVelocity.Y = MathHelper.Clamp(value.Y, -100.0f, 100.0f);
} }
+5
View File
@@ -45,6 +45,11 @@ namespace Subsurface
get { return Vector2.Zero; } get { return Vector2.Zero; }
} }
public AITarget AiTarget
{
get { return aiTarget; }
}
public Entity() public Entity()
{ {
//give an unique ID //give an unique ID
+5 -2
View File
@@ -505,7 +505,7 @@ namespace Subsurface
private void Translate(Vector2 amount) private void Translate(Vector2 amount)
{ {
if (amount == Vector2.Zero || ! amount.IsValid()) return; if (amount == Vector2.Zero || !amount.IsValid()) return;
Level.Loaded.Move(-amount); Level.Loaded.Move(-amount);
} }
@@ -587,8 +587,11 @@ namespace Subsurface
newSpeed = new Vector2(message.ReadFloat(), message.ReadFloat()); newSpeed = new Vector2(message.ReadFloat(), message.ReadFloat());
} }
catch catch (Exception e)
{ {
#if DEBUG
DebugConsole.ThrowError("invalid network message", e);
#endif
return; return;
} }
+22 -7
View File
@@ -72,13 +72,18 @@ namespace Subsurface.Networking
myCharacter = Character.Controlled; myCharacter = Character.Controlled;
// Create new instance of configs. Parameter is "application Id". It has to be same on client and server. // Create new instance of configs. Parameter is "application Id". It has to be same on client and server.
NetPeerConfiguration Config = new NetPeerConfiguration("subsurface"); NetPeerConfiguration config = new NetPeerConfiguration("subsurface");
//Config.SimulatedLoss = 0.2f; #if DEBUG
//Config.SimulatedMinimumLatency = 0.5f; config.SimulatedLoss = 0.2f;
config.SimulatedMinimumLatency = 0.3f;
#endif
config.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt
| NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error);
// Create new client, with previously created configs // Create new client, with previously created configs
client = new NetClient(Config); client = new NetClient(config);
NetOutgoingMessage outmsg = client.CreateMessage(); NetOutgoingMessage outmsg = client.CreateMessage();
client.Start(); client.Start();
@@ -267,9 +272,19 @@ namespace Subsurface.Networking
Character.Controlled = null; Character.Controlled = null;
Game1.GameScreen.Cam.TargetPos = Vector2.Zero; Game1.GameScreen.Cam.TargetPos = Vector2.Zero;
} }
else else if (gameStarted)
{ {
if (gameStarted) new NetworkEvent(myCharacter.ID, true); Vector2 charMovement = myCharacter.AnimController.TargetMovement;
if ((charMovement==Vector2.Zero || charMovement.Length()<0.001f) &&
!myCharacter.ActionKeyDown.State && !myCharacter.SecondaryKeyDown.State)
{
new NetworkEvent(NetworkEventType.NotMoving, myCharacter.ID, true);
}
else
{
new NetworkEvent(myCharacter.ID, true);
}
} }
} }
+35 -6
View File
@@ -30,7 +30,7 @@ namespace Subsurface.Networking
private Client myClient; private Client myClient;
public GameServer(string name, int port, bool isPublic = false, string password="", bool attemptUPnP = false, int maxPlayers = 10) public GameServer(string name, int port, bool isPublic = false, string password = "", bool attemptUPnP = false, int maxPlayers = 10)
{ {
var endRoundButton = new GUIButton(new Rectangle(Game1.GraphicsWidth - 290, 20, 150, 25), "End round", Alignment.TopLeft, GUI.style, inGameHUD); var endRoundButton = new GUIButton(new Rectangle(Game1.GraphicsWidth - 290, 20, 150, 25), "End round", Alignment.TopLeft, GUI.style, inGameHUD);
endRoundButton.OnClicked = EndButtonHit; endRoundButton.OnClicked = EndButtonHit;
@@ -41,8 +41,10 @@ namespace Subsurface.Networking
config = new NetPeerConfiguration("subsurface"); config = new NetPeerConfiguration("subsurface");
//config.SimulatedLoss = 0.2f; #if DEBUG
//config.SimulatedMinimumLatency = 0.5f; config.SimulatedLoss = 0.2f;
config.SimulatedMinimumLatency = 0.3f;
#endif
config.Port = port; config.Port = port;
Port = port; Port = port;
@@ -53,6 +55,9 @@ namespace Subsurface.Networking
} }
config.MaximumConnections = maxPlayers; config.MaximumConnections = maxPlayers;
config.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt
| NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error);
config.EnableMessageType(NetIncomingMessageType.ConnectionApproval); config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
@@ -457,6 +462,31 @@ namespace Subsurface.Networking
{ {
//System.Diagnostics.Debug.WriteLine("networkevent "+networkEvent.ID); //System.Diagnostics.Debug.WriteLine("networkevent "+networkEvent.ID);
List<NetConnection> recipients = new List<NetConnection>();
if (!networkEvent.IsImportant)
{
Entity e = Entity.FindEntityByID(networkEvent.ID);
foreach (Client c in connectedClients)
{
if (c.character==null) continue;
if (Vector2.Distance(e.SimPosition, c.character.SimPosition) > 2000.0f) continue;
recipients.Add(c.Connection);
}
}
else
{
foreach (Client c in connectedClients)
{
if (c.character == null) continue;
recipients.Add(c.Connection);
}
}
if (recipients.Count == 0) return;
NetOutgoingMessage message = server.CreateMessage(); NetOutgoingMessage message = server.CreateMessage();
message.Write((byte)PacketTypes.NetworkEvent); message.Write((byte)PacketTypes.NetworkEvent);
//if (!networkEvent.IsClient) continue; //if (!networkEvent.IsClient) continue;
@@ -467,7 +497,7 @@ namespace Subsurface.Networking
if (server.ConnectionsCount>0) if (server.ConnectionsCount>0)
{ {
server.SendMessage(message, server.Connections, server.SendMessage(message, recipients,
(networkEvent.IsImportant) ? NetDeliveryMethod.Unreliable : NetDeliveryMethod.ReliableUnordered, 0); (networkEvent.IsImportant) ? NetDeliveryMethod.Unreliable : NetDeliveryMethod.ReliableUnordered, 0);
} }
@@ -703,8 +733,7 @@ namespace Subsurface.Networking
spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + server.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White); spriteBatch.DrawString(GUI.SmallFont, "Sent bytes: " + server.Statistics.SentBytes, new Vector2(x + 10, y + 75), Color.White);
spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White); spriteBatch.DrawString(GUI.SmallFont, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
y += 110; y += 110;
foreach (Client c in connectedClients) foreach (Client c in connectedClients)
{ {
+3 -2
View File
@@ -11,14 +11,15 @@ namespace Subsurface.Networking
DropItem = 3, DropItem = 3,
InventoryUpdate = 4, InventoryUpdate = 4,
PickItem = 5, PickItem = 5,
UpdateProperty = 6 UpdateProperty = 6,
NotMoving = 7
} }
class NetworkEvent class NetworkEvent
{ {
public static List<NetworkEvent> events = new List<NetworkEvent>(); public static List<NetworkEvent> events = new List<NetworkEvent>();
private static bool[] isImportant = { false, true, false, true, true, true }; private static bool[] isImportant = { false, true, false, true, true, true, true, false };
private int id; private int id;
+40 -9
View File
@@ -7,6 +7,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Subsurface.Networking; using Subsurface.Networking;
using System.Collections.Generic; using System.Collections.Generic;
using System;
namespace Subsurface namespace Subsurface
{ {
@@ -48,6 +49,7 @@ namespace Subsurface
get { return targetPosition; } get { return targetPosition; }
set set
{ {
if (float.IsNaN(value.X) || float.IsNaN(value.Y)) return;
targetPosition.X = MathHelper.Clamp(value.X, -10000.0f, 10000.0f); targetPosition.X = MathHelper.Clamp(value.X, -10000.0f, 10000.0f);
targetPosition.Y = MathHelper.Clamp(value.Y, -10000.0f, 10000.0f); targetPosition.Y = MathHelper.Clamp(value.Y, -10000.0f, 10000.0f);
} }
@@ -57,7 +59,8 @@ namespace Subsurface
{ {
get { return targetVelocity; } get { return targetVelocity; }
set set
{ {
if (float.IsNaN(value.X) || float.IsNaN(value.Y)) return;
targetVelocity.X = MathHelper.Clamp(value.X, -100.0f, 100.0f); targetVelocity.X = MathHelper.Clamp(value.X, -100.0f, 100.0f);
targetVelocity.Y = MathHelper.Clamp(value.Y, -100.0f, 100.0f); targetVelocity.Y = MathHelper.Clamp(value.Y, -100.0f, 100.0f);
} }
@@ -68,7 +71,7 @@ namespace Subsurface
get { return targetRotation; } get { return targetRotation; }
set set
{ {
if (float.IsNaN(value) || float.IsInfinity(value) || float.IsNegativeInfinity(value)) return; if (float.IsNaN(value) || float.IsInfinity(value)) return;
targetRotation = value; targetRotation = value;
} }
} }
@@ -76,7 +79,11 @@ namespace Subsurface
public float TargetAngularVelocity public float TargetAngularVelocity
{ {
get { return targetAngularVelocity; } get { return targetAngularVelocity; }
set { targetAngularVelocity = value; } set
{
if (float.IsNaN(value) || float.IsInfinity(value)) return;
targetAngularVelocity = value;
}
} }
public Vector2 DrawPosition public Vector2 DrawPosition
@@ -356,13 +363,37 @@ namespace Subsurface
public void ReadNetworkData(NetworkEventType type, NetIncomingMessage message) public void ReadNetworkData(NetworkEventType type, NetIncomingMessage message)
{ {
targetPosition.X = message.ReadFloat(); Vector2 newTargetPos = Vector2.Zero;
targetPosition.Y = message.ReadFloat(); Vector2 newTargetVel = Vector2.Zero;
targetVelocity.X = message.ReadFloat();
targetVelocity.Y = message.ReadFloat(); float newTargetRotation = 0.0f, newTargetAngularVel = 0.0f;
try
{
newTargetPos = new Vector2(message.ReadFloat(),message.ReadFloat());
newTargetVel = new Vector2(message.ReadFloat(),message.ReadFloat());
newTargetRotation = message.ReadFloat();
newTargetAngularVel = message.ReadFloat();
}
catch (Exception e)
{
#if DEBUG
DebugConsole.ThrowError("invalid network message", e);
#endif
return;
}
if (!MathUtils.IsValid(newTargetPos) || !MathUtils.IsValid(newTargetVel) ||
!MathUtils.IsValid(newTargetRotation) || !MathUtils.IsValid(newTargetAngularVel)) return;
targetPosition = newTargetPos;
targetVelocity = newTargetVel;
targetRotation = newTargetRotation;
targetAngularVelocity = newTargetAngularVel;
targetRotation = message.ReadFloat();
targetAngularVelocity = message.ReadFloat();
} }
} }
} }
+12
View File
@@ -27,6 +27,18 @@ namespace Subsurface
return (float)Math.Atan2(vector.Y, vector.X); return (float)Math.Atan2(vector.Y, vector.X);
} }
public static bool IsValid(float value)
{
return (!float.IsInfinity(value) && !float.IsInfinity(value));
}
public static bool IsValid(Vector2 vector)
{
return (!float.IsInfinity(vector.X) && !float.IsInfinity(vector.Y) && !float.IsNaN(vector.X) && !float.IsNaN(vector.Y));
}
public static float CurveAngle(float from, float to, float step) public static float CurveAngle(float from, float to, float step)
{ {
Binary file not shown.