basic Sync checking. No protocol stuff yet; just checks that input events are well-behaved.
This commit is contained in:
@@ -46,5 +46,10 @@ namespace OpenRa
|
|||||||
if( i.Value is T )
|
if( i.Value is T )
|
||||||
yield return (T)i.Value;
|
yield return (T)i.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerator<object> GetEnumerator()
|
||||||
|
{
|
||||||
|
return WithInterface<object>().GetEnumerator();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ namespace OpenRa.Game
|
|||||||
{
|
{
|
||||||
class Actor
|
class Actor
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
public readonly TypeDictionary traits = new TypeDictionary();
|
public readonly TypeDictionary traits = new TypeDictionary();
|
||||||
public readonly UnitInfo Info;
|
public readonly UnitInfo Info;
|
||||||
|
|
||||||
public readonly uint ActorID;
|
public readonly uint ActorID;
|
||||||
|
[Sync]
|
||||||
public int2 Location;
|
public int2 Location;
|
||||||
|
[Sync]
|
||||||
public Player Owner;
|
public Player Owner;
|
||||||
|
[Sync]
|
||||||
public int Health;
|
public int Health;
|
||||||
IActivity currentActivity;
|
IActivity currentActivity;
|
||||||
|
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ namespace OpenRa.Game
|
|||||||
shpRenderer.Flush();
|
shpRenderer.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawChat()
|
void DrawChat()
|
||||||
{
|
{
|
||||||
var chatpos = new int2(400, Game.viewport.Height - 20);
|
var chatpos = new int2(400, Game.viewport.Height - 20);
|
||||||
|
|||||||
@@ -147,14 +147,24 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
public Cursor ChooseCursor()
|
public Cursor ChooseCursor()
|
||||||
{
|
{
|
||||||
var mi = new MouseInput
|
int sync = Game.world.SyncHash();
|
||||||
{
|
|
||||||
Location = (Game.CellSize * MousePosition - Game.viewport.Location).ToInt2(),
|
|
||||||
Button = MouseButton.Right,
|
|
||||||
Modifiers = GetModifierKeys(),
|
|
||||||
};
|
|
||||||
|
|
||||||
return orderGenerator.GetCursor(MousePosition.ToInt2(), mi);
|
try
|
||||||
|
{
|
||||||
|
var mi = new MouseInput
|
||||||
|
{
|
||||||
|
Location = ( Game.CellSize * MousePosition - Game.viewport.Location ).ToInt2(),
|
||||||
|
Button = MouseButton.Right,
|
||||||
|
Modifiers = GetModifierKeys(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return orderGenerator.GetCursor( MousePosition.ToInt2(), mi );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if( sync != Game.world.SyncHash() )
|
||||||
|
throw new InvalidOperationException( "Desync in Controller.ChooseCursor" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cache<int, List<Actor>> controlGroups = new Cache<int, List<Actor>>(_ => new List<Actor>());
|
Cache<int, List<Actor>> controlGroups = new Cache<int, List<Actor>>(_ => new List<Actor>());
|
||||||
|
|||||||
0
OpenRa.Game/Effects/Bullet.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Bullet.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Corpse.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Corpse.cs
Normal file → Executable file
0
OpenRa.Game/Effects/DelayedAction.cs
Normal file → Executable file
0
OpenRa.Game/Effects/DelayedAction.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Explosion.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Explosion.cs
Normal file → Executable file
0
OpenRa.Game/Effects/FlashTarget.cs
Normal file → Executable file
0
OpenRa.Game/Effects/FlashTarget.cs
Normal file → Executable file
0
OpenRa.Game/Effects/GpsSatellite.cs
Normal file → Executable file
0
OpenRa.Game/Effects/GpsSatellite.cs
Normal file → Executable file
0
OpenRa.Game/Effects/IEffect.cs
Normal file → Executable file
0
OpenRa.Game/Effects/IEffect.cs
Normal file → Executable file
0
OpenRa.Game/Effects/InvulnEffect.cs
Normal file → Executable file
0
OpenRa.Game/Effects/InvulnEffect.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Missile.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Missile.cs
Normal file → Executable file
0
OpenRa.Game/Effects/MoveFlash.cs
Normal file → Executable file
0
OpenRa.Game/Effects/MoveFlash.cs
Normal file → Executable file
0
OpenRa.Game/Effects/PowerDownIndicator.cs
Normal file → Executable file
0
OpenRa.Game/Effects/PowerDownIndicator.cs
Normal file → Executable file
0
OpenRa.Game/Effects/RepairIndicator.cs
Normal file → Executable file
0
OpenRa.Game/Effects/RepairIndicator.cs
Normal file → Executable file
0
OpenRa.Game/Effects/SatelliteLaunch.cs
Normal file → Executable file
0
OpenRa.Game/Effects/SatelliteLaunch.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Smoke.cs
Normal file → Executable file
0
OpenRa.Game/Effects/Smoke.cs
Normal file → Executable file
@@ -95,6 +95,8 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e)
|
void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
|
int sync = Game.world.SyncHash();
|
||||||
|
|
||||||
Game.viewport.DispatchMouseInput(
|
Game.viewport.DispatchMouseInput(
|
||||||
new MouseInput
|
new MouseInput
|
||||||
{
|
{
|
||||||
@@ -103,6 +105,9 @@ namespace OpenRa.Game
|
|||||||
Location = new int2(e.Location),
|
Location = new int2(e.Location),
|
||||||
Modifiers = (Modifiers)(int)ModifierKeys,
|
Modifiers = (Modifiers)(int)ModifierKeys,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if( sync != Game.world.SyncHash() )
|
||||||
|
throw new InvalidOperationException( "Desync in DispatchMouseInput" );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMouseDown(MouseEventArgs e)
|
protected override void OnMouseDown(MouseEventArgs e)
|
||||||
@@ -136,6 +141,8 @@ namespace OpenRa.Game
|
|||||||
{
|
{
|
||||||
base.OnKeyDown(e);
|
base.OnKeyDown(e);
|
||||||
|
|
||||||
|
int sync = Game.world.SyncHash();
|
||||||
|
|
||||||
/* hack hack hack */
|
/* hack hack hack */
|
||||||
if (e.KeyCode == Keys.F8 && !Game.orderManager.GameStarted)
|
if (e.KeyCode == Keys.F8 && !Game.orderManager.GameStarted)
|
||||||
{
|
{
|
||||||
@@ -156,16 +163,24 @@ namespace OpenRa.Game
|
|||||||
if (!Game.chat.isChatting)
|
if (!Game.chat.isChatting)
|
||||||
if (e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9)
|
if (e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9)
|
||||||
Game.controller.DoControlGroup( (int)e.KeyCode - (int)Keys.D0, (Modifiers)(int)e.Modifiers );
|
Game.controller.DoControlGroup( (int)e.KeyCode - (int)Keys.D0, (Modifiers)(int)e.Modifiers );
|
||||||
|
|
||||||
|
if( sync != Game.world.SyncHash() )
|
||||||
|
throw new InvalidOperationException( "Desync in OnKeyDown" );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnKeyPress(KeyPressEventArgs e)
|
protected override void OnKeyPress(KeyPressEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnKeyPress(e);
|
base.OnKeyPress(e);
|
||||||
|
|
||||||
|
int sync = Game.world.SyncHash();
|
||||||
|
|
||||||
if (e.KeyChar == '\r')
|
if (e.KeyChar == '\r')
|
||||||
Game.chat.Toggle();
|
Game.chat.Toggle();
|
||||||
else if (Game.chat.isChatting)
|
else if (Game.chat.isChatting)
|
||||||
Game.chat.TypeChar(e.KeyChar);
|
Game.chat.TypeChar(e.KeyChar);
|
||||||
|
|
||||||
|
if( sync != Game.world.SyncHash() )
|
||||||
|
throw new InvalidOperationException( "Desync in OnKeyPress" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,7 @@
|
|||||||
<Compile Include="SupportPowers\NullPower.cs" />
|
<Compile Include="SupportPowers\NullPower.cs" />
|
||||||
<Compile Include="Support\Stopwatch.cs" />
|
<Compile Include="Support\Stopwatch.cs" />
|
||||||
<Compile Include="Support\PerfHistory.cs" />
|
<Compile Include="Support\PerfHistory.cs" />
|
||||||
|
<Compile Include="Sync.cs" />
|
||||||
<Compile Include="Traits\AcceptsOre.cs" />
|
<Compile Include="Traits\AcceptsOre.cs" />
|
||||||
<Compile Include="Traits\Activities\Attack.cs" />
|
<Compile Include="Traits\Activities\Attack.cs" />
|
||||||
<Compile Include="Traits\Activities\CaptureBuilding.cs" />
|
<Compile Include="Traits\Activities\CaptureBuilding.cs" />
|
||||||
@@ -318,4 +319,4 @@
|
|||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
</Project>
|
</Project>
|
||||||
@@ -30,7 +30,7 @@ namespace OpenRa.Game
|
|||||||
this.SubjectId = subjectId;
|
this.SubjectId = subjectId;
|
||||||
this.TargetActorId = targetActorId;
|
this.TargetActorId = targetActorId;
|
||||||
this.TargetLocation = targetLocation;
|
this.TargetLocation = targetLocation;
|
||||||
this.TargetString = targetString;
|
this.TargetString = targetString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Validate()
|
public bool Validate()
|
||||||
|
|||||||
57
OpenRa.Game/Sync.cs
Executable file
57
OpenRa.Game/Sync.cs
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace OpenRa.Game
|
||||||
|
{
|
||||||
|
class SyncAttribute : Attribute { }
|
||||||
|
|
||||||
|
static class Sync
|
||||||
|
{
|
||||||
|
public static int CalculateSyncHash( object obj )
|
||||||
|
{
|
||||||
|
int hash = 0; // TODO: start with a more interesting initial value.
|
||||||
|
|
||||||
|
// TODO: cache the Syncable fields; maybe use DynamicMethod to make this fast?
|
||||||
|
// FIXME: does GetFields even give fields in a well-defined order?
|
||||||
|
const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||||
|
foreach( var field in obj.GetType().GetFields( bf ).Where( x => x.GetCustomAttributes( typeof( SyncAttribute ), true ).Length != 0 ) )
|
||||||
|
{
|
||||||
|
if( field.FieldType == typeof( int ) )
|
||||||
|
hash ^= (int)field.GetValue( obj );
|
||||||
|
|
||||||
|
else if( field.FieldType == typeof( Actor ) )
|
||||||
|
{
|
||||||
|
var a = (Actor)field.GetValue( obj );
|
||||||
|
if( a != null )
|
||||||
|
hash ^= (int)( a.ActorID << 16 );
|
||||||
|
}
|
||||||
|
else if( field.FieldType == typeof( TypeDictionary ) )
|
||||||
|
{
|
||||||
|
foreach( var o in (TypeDictionary)field.GetValue( obj ) )
|
||||||
|
hash += CalculateSyncHash( o );
|
||||||
|
}
|
||||||
|
else if( field.FieldType == typeof( bool ) )
|
||||||
|
hash ^= (bool)field.GetValue( obj ) ? 0xaaa : 0x555;
|
||||||
|
|
||||||
|
else if( field.FieldType == typeof( int2 ) )
|
||||||
|
{
|
||||||
|
var i2 = (int2)field.GetValue( obj );
|
||||||
|
hash ^= ( ( i2.X * 5 ) ^ ( i2.Y * 3 ) ) / 4;
|
||||||
|
}
|
||||||
|
else if( field.FieldType == typeof( Player ) )
|
||||||
|
{
|
||||||
|
var p = (Player)field.GetValue( obj );
|
||||||
|
if( p != null )
|
||||||
|
hash ^= p.Index * 0x567;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new NotImplementedException( "SyncAttribute on unhashable field" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,10 +8,12 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class AttackBase : IIssueOrder, IResolveOrder, ITick
|
class AttackBase : IIssueOrder, IResolveOrder, ITick
|
||||||
{
|
{
|
||||||
public Actor target;
|
[Sync] public Actor target;
|
||||||
|
|
||||||
// time (in frames) until each weapon can fire again.
|
// time (in frames) until each weapon can fire again.
|
||||||
|
[Sync]
|
||||||
protected int primaryFireDelay = 0;
|
protected int primaryFireDelay = 0;
|
||||||
|
[Sync]
|
||||||
protected int secondaryFireDelay = 0;
|
protected int secondaryFireDelay = 0;
|
||||||
|
|
||||||
int primaryBurst;
|
int primaryBurst;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace OpenRa.Game.Traits
|
|||||||
public AttackFrontal(Actor self, int facingTolerance)
|
public AttackFrontal(Actor self, int facingTolerance)
|
||||||
: base(self) { FacingTolerance = facingTolerance; }
|
: base(self) { FacingTolerance = facingTolerance; }
|
||||||
|
|
||||||
int FacingTolerance;
|
readonly int FacingTolerance;
|
||||||
|
|
||||||
public override void Tick(Actor self)
|
public override void Tick(Actor self)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
public readonly BuildingInfo unitInfo;
|
public readonly BuildingInfo unitInfo;
|
||||||
|
[Sync]
|
||||||
bool isRepairing = false;
|
bool isRepairing = false;
|
||||||
|
[Sync]
|
||||||
bool manuallyDisabled = false;
|
bool manuallyDisabled = false;
|
||||||
public bool ManuallyDisabled { get { return manuallyDisabled; } }
|
public bool ManuallyDisabled { get { return manuallyDisabled; } }
|
||||||
public bool Disabled { get { return (manuallyDisabled || (unitInfo.Powered && self.Owner.GetPowerState() != PowerState.Normal)); } }
|
public bool Disabled { get { return (manuallyDisabled || (unitInfo.Powered && self.Owner.GetPowerState() != PowerState.Normal)); } }
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ namespace OpenRa.Game.Traits
|
|||||||
class ChronoshiftDeploy : IIssueOrder, IResolveOrder, ISpeedModifier, ITick, IPips
|
class ChronoshiftDeploy : IIssueOrder, IResolveOrder, ISpeedModifier, ITick, IPips
|
||||||
{
|
{
|
||||||
// Recharge logic
|
// Recharge logic
|
||||||
|
[Sync]
|
||||||
int chargeTick = 0; // How long until we can chronoshift again?
|
int chargeTick = 0; // How long until we can chronoshift again?
|
||||||
int chargeLength = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts?
|
readonly int chargeLength = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts?
|
||||||
|
|
||||||
public ChronoshiftDeploy(Actor self) { }
|
public ChronoshiftDeploy(Actor self) { }
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ namespace OpenRa.Game.Traits
|
|||||||
class Chronoshiftable : IResolveOrder, ISpeedModifier, ITick
|
class Chronoshiftable : IResolveOrder, ISpeedModifier, ITick
|
||||||
{
|
{
|
||||||
// Return-to-sender logic
|
// Return-to-sender logic
|
||||||
|
[Sync]
|
||||||
int2 chronoshiftOrigin;
|
int2 chronoshiftOrigin;
|
||||||
|
[Sync]
|
||||||
int chronoshiftReturnTicks = 0;
|
int chronoshiftReturnTicks = 0;
|
||||||
|
|
||||||
public Chronoshiftable(Actor self) { }
|
public Chronoshiftable(Actor self) { }
|
||||||
|
|
||||||
public void Tick(Actor self)
|
public void Tick(Actor self)
|
||||||
@@ -65,7 +67,7 @@ namespace OpenRa.Game.Traits
|
|||||||
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
|
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
|
||||||
|
|
||||||
var power = self.Owner.SupportPowers[order.TargetString].Impl;
|
var power = self.Owner.SupportPowers[order.TargetString].Impl;
|
||||||
power.OnFireNotification(self, self.Location);
|
power.OnFireNotification(self, self.Location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class Cloak : IRenderModifier, INotifyAttack, ITick
|
class Cloak : IRenderModifier, INotifyAttack, ITick
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
int remainingUncloakTime = 2; /* setup for initial cloak */
|
int remainingUncloakTime = 2; /* setup for initial cloak */
|
||||||
|
|
||||||
public Cloak(Actor self) {}
|
public Cloak(Actor self) {}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class Harvester : IIssueOrder, IResolveOrder, IPips
|
class Harvester : IIssueOrder, IResolveOrder, IPips
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
public int oreCarried = 0; /* sum of these must not exceed capacity */
|
public int oreCarried = 0; /* sum of these must not exceed capacity */
|
||||||
|
[Sync]
|
||||||
public int gemsCarried = 0;
|
public int gemsCarried = 0;
|
||||||
|
|
||||||
public bool IsFull { get { return oreCarried + gemsCarried == Rules.General.BailCount; } }
|
public bool IsFull { get { return oreCarried + gemsCarried == Rules.General.BailCount; } }
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class IronCurtainable : IResolveOrder, IDamageModifier, ITick
|
class IronCurtainable : IResolveOrder, IDamageModifier, ITick
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
int RemainingTicks = 0;
|
int RemainingTicks = 0;
|
||||||
|
|
||||||
public IronCurtainable(Actor self) { }
|
public IronCurtainable(Actor self) { }
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class LimitedAmmo : INotifyAttack, IPips
|
class LimitedAmmo : INotifyAttack, IPips
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
int ammo;
|
int ammo;
|
||||||
Actor self;
|
Actor self;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
readonly Actor self;
|
readonly Actor self;
|
||||||
|
|
||||||
|
[Sync]
|
||||||
int2 __fromCell;
|
int2 __fromCell;
|
||||||
public int2 fromCell
|
public int2 fromCell
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ namespace OpenRa.Game.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Key: Production category.
|
// Key: Production category.
|
||||||
|
// TODO: sync this
|
||||||
readonly Cache<string, List<ProductionItem>> production
|
readonly Cache<string, List<ProductionItem>> production
|
||||||
= new Cache<string, List<ProductionItem>>( _ => new List<ProductionItem>() );
|
= new Cache<string, List<ProductionItem>>( _ => new List<ProductionItem>() );
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class RallyPoint : IRender, IIssueOrder, IResolveOrder, ITick
|
class RallyPoint : IRender, IIssueOrder, IResolveOrder, ITick
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
public int2 rallyPoint;
|
public int2 rallyPoint;
|
||||||
public Animation anim;
|
public Animation anim;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ namespace OpenRa.Game.Traits
|
|||||||
class RenderWarFactory : IRender, INotifyBuildComplete, INotifyDamage, ITick, INotifyProduction
|
class RenderWarFactory : IRender, INotifyBuildComplete, INotifyDamage, ITick, INotifyProduction
|
||||||
{
|
{
|
||||||
public Animation roof;
|
public Animation roof;
|
||||||
|
[Sync]
|
||||||
bool doneBuilding;
|
bool doneBuilding;
|
||||||
|
[Sync]
|
||||||
bool isOpen;
|
bool isOpen;
|
||||||
public readonly Actor self;
|
public readonly Actor self;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class Submarine : IRenderModifier, INotifyAttack, ITick, INotifyDamage
|
class Submarine : IRenderModifier, INotifyAttack, ITick, INotifyDamage
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
int remainingSurfaceTime = 2; /* setup for initial dive */
|
int remainingSurfaceTime = 2; /* setup for initial dive */
|
||||||
|
|
||||||
public Submarine(Actor self) { }
|
public Submarine(Actor self) { }
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace OpenRa.Game.Traits
|
|||||||
const float proneDamage = .5f;
|
const float proneDamage = .5f;
|
||||||
const float proneSpeed = .5f;
|
const float proneSpeed = .5f;
|
||||||
|
|
||||||
|
[Sync]
|
||||||
int remainingProneTime = 0;
|
int remainingProneTime = 0;
|
||||||
|
|
||||||
public bool IsProne { get { return remainingProneTime > 0; } }
|
public bool IsProne { get { return remainingProneTime > 0; } }
|
||||||
|
|||||||
@@ -10,18 +10,18 @@ namespace OpenRa.Game.Traits
|
|||||||
// depends on the order of pips in WorldRenderer.cs!
|
// depends on the order of pips in WorldRenderer.cs!
|
||||||
enum PipType { Transparent, Green, Yellow, Red, Gray };
|
enum PipType { Transparent, Green, Yellow, Red, Gray };
|
||||||
enum TagType { None, Fake, Primary };
|
enum TagType { None, Fake, Primary };
|
||||||
|
|
||||||
interface ITick { void Tick(Actor self); }
|
interface ITick { void Tick(Actor self); }
|
||||||
interface IRender { IEnumerable<Renderable> Render(Actor self); }
|
interface IRender { IEnumerable<Renderable> Render(Actor self); }
|
||||||
|
interface IIssueOrder { Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor ); }
|
||||||
|
interface IResolveOrder { void ResolveOrder( Actor self, Order order ); }
|
||||||
|
|
||||||
interface INotifySold { void Sold(Actor self); }
|
interface INotifySold { void Sold(Actor self); }
|
||||||
interface INotifyDamage { void Damaged(Actor self, AttackInfo e); }
|
interface INotifyDamage { void Damaged(Actor self, AttackInfo e); }
|
||||||
interface INotifyBuildComplete { void BuildingComplete (Actor self); }
|
interface INotifyBuildComplete { void BuildingComplete (Actor self); }
|
||||||
interface INotifyProduction { void UnitProduced(Actor self, Actor other); }
|
interface INotifyProduction { void UnitProduced(Actor self, Actor other); }
|
||||||
interface IAcceptThief { void OnSteal(Actor self, Actor thief); }
|
interface IAcceptThief { void OnSteal(Actor self, Actor thief); }
|
||||||
|
|
||||||
interface IIssueOrder { Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor); }
|
|
||||||
interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
|
|
||||||
|
|
||||||
interface IProducer
|
interface IProducer
|
||||||
{
|
{
|
||||||
bool Produce( Actor self, UnitInfo producee );
|
bool Produce( Actor self, UnitInfo producee );
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class Turreted : ITick
|
class Turreted : ITick
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
public int turretFacing = 0;
|
public int turretFacing = 0;
|
||||||
public int? desiredFacing;
|
public int? desiredFacing;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ namespace OpenRa.Game.Traits
|
|||||||
{
|
{
|
||||||
class Unit : INotifyDamage
|
class Unit : INotifyDamage
|
||||||
{
|
{
|
||||||
|
[Sync]
|
||||||
public int Facing;
|
public int Facing;
|
||||||
|
[Sync]
|
||||||
public int Altitude;
|
public int Altitude;
|
||||||
|
|
||||||
public Unit( Actor self ) { }
|
public Unit( Actor self ) { }
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
public void Add(Actor a)
|
public void Add(Actor a)
|
||||||
{
|
{
|
||||||
a.IsInWorld = true;
|
a.IsInWorld = true;
|
||||||
actors.Add(a);
|
actors.Add(a);
|
||||||
ActorAdded(a);
|
ActorAdded(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(Actor a)
|
public void Remove(Actor a)
|
||||||
{
|
{
|
||||||
a.IsInWorld = false;
|
a.IsInWorld = false;
|
||||||
actors.Remove(a);
|
actors.Remove(a);
|
||||||
ActorRemoved(a);
|
ActorRemoved(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,5 +52,14 @@ namespace OpenRa.Game
|
|||||||
{
|
{
|
||||||
return nextAID++;
|
return nextAID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int SyncHash()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
foreach( var a in Actors )
|
||||||
|
ret += (int)a.ActorID * Sync.CalculateSyncHash( a );
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user