Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Build Simitone

on:
workflow_dispatch:
inputs:
configuration:
description: 'Build configuration'
required: false
default: 'Release'
type: choice
options:
- Release
- Debug

jobs:
build:
runs-on: windows-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive

- name: Setup .NET 9
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'

- name: Run Protobuild
shell: pwsh
run: |
cd FreeSO/Other/libs/FSOMonoGame/
./protobuild.exe --generate
continue-on-error: true

- name: Restore Simitone dependencies
run: dotnet restore Client/Simitone/Simitone.sln

- name: Restore FreeSO dependencies
run: dotnet restore FreeSO/TSOClient/FreeSO.sln
continue-on-error: true

- name: Restore Roslyn dependencies
shell: pwsh
run: |
cd FreeSO/TSOClient/FSO.SimAntics.JIT.Roslyn/
dotnet restore
continue-on-error: true

- name: Build
run: dotnet build Client/Simitone/Simitone.sln -c ${{ inputs.configuration || 'Release' }} --no-restore

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: SimitoneWindows-${{ inputs.configuration || 'Release' }}
path: Client/Simitone/Simitone.Windows/bin/${{ inputs.configuration || 'Release' }}/net9.0-windows/
if-no-files-found: error
43 changes: 42 additions & 1 deletion Client/Simitone/Simitone.Client/UI/Panels/UILotControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -757,10 +757,51 @@ public override void Update(UpdateState state)

if (!FoundMe && ActiveEntity != null)
{
vm.Context.World.State.CenterTile = new Vector2(ActiveEntity.VisualPosition.X, ActiveEntity.VisualPosition.Y);
// Send change control command to ensure sim is properly selected
// This sets PersistID, registers in ObjectQueries, sets Global 3, and centers camera
vm.SendCommand(new VMNetChangeControlCmd() { TargetID = ActiveEntity.ObjectID });
FoundMe = true;
}

// Fallback: if no sim with expected PersistID, take control of any available avatar
if (!FoundMe && ActiveEntity == null && vm.Context.ObjectQueries.Avatars.Count > 0)
{
var fallbackAvatar = vm.Context.ObjectQueries.Avatars.FirstOrDefault();
if (fallbackAvatar != null)
{
// Send change control command to properly select this sim
// This sets PersistID, registers in ObjectQueries, sets Global 3, and centers camera
vm.SendCommand(new VMNetChangeControlCmd() { TargetID = fallbackAvatar.ObjectID });
FoundMe = true;
}
}

// Fallback for empty lots (no avatars): center on mailbox, any placed object, or lot center
if (!FoundMe && vm.Context.ObjectQueries.Avatars.Count == 0)
{
// Try to find mailbox first (GUIDs: 0xEF121974 or 0x1D95C9B0)
var landmark = vm.Entities.FirstOrDefault(x => x.Object.OBJ.GUID == 0xEF121974 || x.Object.OBJ.GUID == 0x1D95C9B0);

// If no mailbox, try to find any object that's placed on the lot (for community lots)
if (landmark == null)
{
landmark = vm.Entities.FirstOrDefault(x => x.Position != LotTilePos.OUT_OF_WORLD && x.Position.Level == 1);
}

if (landmark != null)
{
vm.Context.World.State.CenterTile = new Vector2(landmark.VisualPosition.X, landmark.VisualPosition.Y);
}
else
{
// Default to lot center
var lotSize = vm.Context.Architecture.Width;
vm.Context.World.State.CenterTile = new Vector2(lotSize / 2f, lotSize / 2f);
}
vm.Context.World.State.ScrollAnchor = null;
FoundMe = true;
}

Queue.QueueOwner = ActiveEntity;
}

Expand Down