{$MODE OBJFPC} { -*- delphi -*- } {$INCLUDE settings.inc} unit staffing; interface uses basenetwork, systems, serverstream, materials, techtree, messageport, isdprotocol; // TODO: create bus // TODO: make population feature report to bus type TStaffingFeatureClass = class(TFeatureClass) strict protected FJobs: Cardinal; function GetFeatureNodeClass(): FeatureNodeReference; override; public constructor CreateFromTechnologyTree(Reader: TTechTreeReader); override; function InitFeatureNode(): TFeatureNode; override; property Jobs: Cardinal read FJobs; end; TStaffingFeatureNode = class(TFeatureNode) strict private FFeatureClass: TStaffingFeatureClass; FBus: TPeopleBusFeatureNode; FPriority: TPriority; // TODO: if equal to NoBusPriority, should reset to zero when ancestor chain changes FAssignedStaff: Cardinal; protected function HandleBusMessage(Message: TBusMessage): Boolean; override; procedure Serialize(DynastyIndex: Cardinal; Writer: TServerStreamWriter; CachedSystem: TSystem); override; public constructor Create(AFeatureClass: TBuilderFeatureClass); destructor Destroy(); override; procedure HandleChanges(CachedSystem: TSystem); override; procedure UpdateJournal(Journal: TJournalWriter; CachedSystem: TSystem); override; procedure ApplyJournal(Journal: TJournalReader; CachedSystem: TSystem); override; function HandleCommand(Command: UTF8String; var Message: TMessage): Boolean; override; procedure PeopleBusAssignStaff(Count: Cardinal); procedure PeopleBusReset(); function GetPriority(): TPriority; procedure SetAutoPriority(Value: TAutoPriority); end; implementation uses exceptions, sysutils, systemnetwork, systemdynasty, isderrors, knowledge, messages, typedump, commonbuses; constructor TStaffingFeatureClass.CreateFromTechnologyTree(Reader: TTechTreeReader); begin inherited Create(); FJobs := ReadNumber(Reader.Tokens, 1, High(FJobs)); // $R- Reader.Tokens.ReadIdentifier('jobs'); end; function TStaffingFeatureClass.GetFeatureNodeClass(): FeatureNodeReference; begin Result := TStaffingFeatureNode; end; function TStaffingFeatureClass.InitFeatureNode(): TFeatureNode; begin Result := TStaffingFeatureNode.Create(Self); end; constructor TStaffingFeatureNode.Create(AFeatureClass: TBuilderFeatureClass); begin inherited Create(); FFeatureClass := AFeatureClass; end; destructor TStaffingFeatureNode.Destroy(); begin if (Assigned(FBus)) then FBus.RemoveEmployer(Self); inherited; end; procedure TStaffingFeatureNode.HandleChanges(CachedSystem: TSystem); var DisabledReasons: TDisabledReasons; Message: TRegisterJobsMessage; begin DisabledReasons := CheckDisabled(Parent); Exclude(DisabledReasons, drUnstaffed); // TODO: consider explicitly listing the reasons for which we wouldn't bother staffing instead if (DisabledReasons <> []) then begin FPriority := 0; if (Assigned(FBus)) then begin FBus.RemoveEmployer(Self); FAssignedStaff := 0; end; end else begin if ((not Assigned(FBus)) and (FPriority <> NoBusPriority)) then begin Message := TRegisterBuilderMessage.Create(Self); if (InjectBusMessage(Message) <> mrHandled) then FPriority := NoBusPriority; FreeAndNil(Message); end; end; inherited; end; function TStaffingFeatureNode.HandleBusMessage(Message: TBusMessage): Boolean; begin if (Message is TCheckDisabledBusMessage) then begin Result := False; if (FAssignedStaff < FFeatureClass.Jobs) then (Message as TCheckDisabledBusMessage).AddReason(drUnstaffed); end else Result := inherited; end; procedure TStaffingFeatureNode.Serialize(DynastyIndex: Cardinal; Writer: TServerStreamWriter; CachedSystem: TSystem); var Visibility: TVisibility; begin Visibility := Parent.ReadVisibilityFor(DynastyIndex, CachedSystem); if (dmDetectable * Visibility <> []) then begin Writer.WriteCardinal(fcStaffing); if ([dmClassKnown, dmInternals] * Visibility <> []) then begin Writer.WriteCardinal(FFeatureClass.Jobs); end else begin Writer.WriteCardinal(0); end; Writer.WriteCardinal(FAssignedStaff); end; end; procedure TStaffingFeatureNode.UpdateJournal(Journal: TJournalWriter; CachedSystem: TSystem); begin Journal.WriteCardinal(FPriority); end; procedure TStaffingFeatureNode.ApplyJournal(Journal: TJournalReader; CachedSystem: TSystem); begin FPriority := Journal.ReadCardinal(); end; initialization Writeln(SizeOf(TStaffingFeatureNode)); RegisterFeatureClass(TStaffingFeatureClass); end.