From f2b1a3a5b86b7a8adfb9ce2f6867810b05969217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=88=AA=E5=91=B3=E9=BA=BB=E9=85=B1?= <93972760+TaranDahl@users.noreply.github.com> Date: Tue, 10 Mar 2026 23:50:32 +0800 Subject: [PATCH 1/5] core --- CREDITS.md | 1 + Phobos.vcxproj | 4 ++ README.md | 4 ++ docs/Whats-New.md | 1 + src/Interop/AttachEffect.cpp | 117 +++++++++++++++++++++++++++++++++++ src/Interop/AttachEffect.h | 34 ++++++++++ src/Interop/TechnoExt.cpp | 10 +++ src/Interop/TechnoExt.h | 6 ++ 8 files changed, 177 insertions(+) create mode 100644 src/Interop/AttachEffect.cpp create mode 100644 src/Interop/AttachEffect.h create mode 100644 src/Interop/TechnoExt.cpp create mode 100644 src/Interop/TechnoExt.h diff --git a/CREDITS.md b/CREDITS.md index 7ca3132006..9616d31e06 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -717,6 +717,7 @@ This page lists all the individual contributions to the project by their author. - Fix an issue that the move mission of the jumpjet does not end correctly - Fix the issue that the Jumpjet must end its movement before starting the next mission - Taunt warhead + - Export interface for external call - **solar-III (凤九歌)** - Target scanning delay customization (documentation) - Skip target scanning function calling for unarmed technos (documentation) diff --git a/Phobos.vcxproj b/Phobos.vcxproj index d45a6ac91f..ac9389869b 100644 --- a/Phobos.vcxproj +++ b/Phobos.vcxproj @@ -30,6 +30,8 @@ + + @@ -221,6 +223,8 @@ + + diff --git a/README.md b/README.md index 52c77fe94d..e184ce4c24 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,10 @@ Credits This project was founded by [@Belonit](https://github.com/Belonit) (Gluk-v48) and [@Metadorius](https://github.com/Metadorius) (Kerbiter) in 2020, with the first public stable release in 2021. Since then it has grown into a large community project with many contributors and maintainers. +### Interoperability + +Phobos has opened the external interfaces of some key components. If you are also developing your own engine extension and wish to use Phobos at the same time, please check out [Interop](./src/Interop). + ### Maintenance crew Maintenance crew consists of experienced Phobos contributors who are recognized and given the permission to maintain and shape the project to the extent of their permissions. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 30d14e66cf..cf58e68352 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -545,6 +545,7 @@ New: - [Taunt warhead](New-or-Enhanced-Logics.md#taunt-warhead) (by TaranDahl) - [Custom hover vehicles shutdown drowning death](New-or-Enhanced-Logics.md#custom-hover-vehicles-shutdown-drowning-death) (by FlyStar) - [SHP turret vehicles support the use of `*tur.shp` files](New-or-Enhanced-Logics.md#independent-shp-vehicle-turret-files) (by FlyStar) +- [Export interface for external call](../README.md#interoperability) (by TaranDahl) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) diff --git a/src/Interop/AttachEffect.cpp b/src/Interop/AttachEffect.cpp new file mode 100644 index 0000000000..3f037f33db --- /dev/null +++ b/src/Interop/AttachEffect.cpp @@ -0,0 +1,117 @@ + +#include "AttachEffect.h" +#include "New/Entity/AttachEffectClass.h" +#include "New/Type/AttachEffectTypeClass.h" + +int __stdcall AE_Attach( + void* pTarget, + void* pInvokerHouse, + void* pInvoker, + void* pSource, + const char** effectTypeNames, + int typeCount, + int durationOverride, + int delay, + int initialDelay, + int recreationDelay +) +{ + if (!pTarget || !effectTypeNames || typeCount <= 0) + return 0; + + TechnoClass* pTargetTechno = static_cast(pTarget); + HouseClass* pInvokerHouseClass = static_cast(pInvokerHouse); + TechnoClass* pInvokerTechno = static_cast(pInvoker); + AbstractClass* pSourceAbs = static_cast(pSource); + + AEAttachInfoTypeClass attachInfo; + + for (int i = 0; i < typeCount; i++) + { + if (effectTypeNames[i]) + { + if (auto pType = AttachEffectTypeClass::Find(effectTypeNames[i])) + attachInfo.AttachTypes.push_back(pType); + } + } + + if (attachInfo.AttachTypes.empty()) + return 0; + + AEAttachParams params; + params.DurationOverride = durationOverride; + params.Delay = delay; + params.InitialDelay = initialDelay; + params.RecreationDelay = recreationDelay; + + int attachedCount = AttachEffectClass::Attach(pTargetTechno, pInvokerHouseClass, pInvokerTechno, pSourceAbs, attachInfo); + + return attachedCount; +} + +int __stdcall AE_Detach( + void* pTarget, + const char** effectTypeNames, + int typeCount +) +{ + if (!pTarget || !effectTypeNames || typeCount <= 0) + return 0; + + TechnoClass* pTargetTechno = static_cast(pTarget); + + AEAttachInfoTypeClass detachInfo; + + for (int i = 0; i < typeCount; i++) + { + if (effectTypeNames[i]) + { + if (auto pType = AttachEffectTypeClass::Find(effectTypeNames[i])) + detachInfo.RemoveTypes.push_back(pType); + } + } + + if (detachInfo.RemoveTypes.empty()) + return 0; + + return AttachEffectClass::Detach(pTargetTechno, detachInfo); +} + +int __stdcall AE_DetachByGroups( + void* pTarget, + const char** groupNames, + int groupCount +) +{ + if (!pTarget || !groupNames || groupCount <= 0) + return 0; + + TechnoClass* pTargetTechno = static_cast(pTarget); + + AEAttachInfoTypeClass detachInfo; + + for (int i = 0; i < groupCount; i++) + { + if (groupNames[i]) + detachInfo.RemoveGroups.push_back(groupNames[i]); + } + + if (detachInfo.RemoveGroups.empty()) + return 0; + + return AttachEffectClass::DetachByGroups(pTargetTechno, detachInfo); +} + +void __stdcall AE_TransferEffects( + void* pSource, + void* pTarget +) +{ + if (!pSource || !pTarget) + return; + + TechnoClass* pSourceTechno = static_cast(pSource); + TechnoClass* pTargetTechno = static_cast(pTarget); + + AttachEffectClass::TransferAttachedEffects(pSourceTechno, pTargetTechno); +} diff --git a/src/Interop/AttachEffect.h b/src/Interop/AttachEffect.h new file mode 100644 index 0000000000..e746cb1b3d --- /dev/null +++ b/src/Interop/AttachEffect.h @@ -0,0 +1,34 @@ +#pragma once + +extern "C" +{ + __declspec(dllexport) int __stdcall AE_Attach( + void* pTarget, + void* pInvokerHouse, + void* pInvoker, + void* pSource, + const char** effectTypeNames, + int typeCount, + int durationOverride, + int delay, + int initialDelay, + int recreationDelay + ); + + __declspec(dllexport) int __stdcall AE_Detach( + void* pTarget, + const char** effectTypeNames, + int typeCount + ); + + __declspec(dllexport) int __stdcall AE_DetachByGroups( + void* pTarget, + const char** groupNames, + int groupCount + ); + + __declspec(dllexport) void __stdcall AE_TransferEffects( + void* pSource, + void* pTarget + ); +} diff --git a/src/Interop/TechnoExt.cpp b/src/Interop/TechnoExt.cpp new file mode 100644 index 0000000000..349e8b7f23 --- /dev/null +++ b/src/Interop/TechnoExt.cpp @@ -0,0 +1,10 @@ +#include "TechnoExt.h" +#include + +extern "C" __declspec(dllexport) bool __stdcall ConvertToType_Phobos(void* pThis, void* toType) +{ + auto pTechno = static_cast(pThis); + auto pType = static_cast(toType); + + return TechnoExt::ConvertToType(pTechno, pType); +} diff --git a/src/Interop/TechnoExt.h b/src/Interop/TechnoExt.h new file mode 100644 index 0000000000..4e43272f41 --- /dev/null +++ b/src/Interop/TechnoExt.h @@ -0,0 +1,6 @@ +#pragma once + +extern "C" +{ + __declspec(dllexport) bool __stdcall ConvertToType_Phobos(void* pThis, void* toType); +} From 1c8132f26e30632a20f65e89970c9ac3681ac07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=88=AA=E5=91=B3=E9=BA=BB=E9=85=B1?= <93972760+TaranDahl@users.noreply.github.com> Date: Wed, 11 Mar 2026 00:21:57 +0800 Subject: [PATCH 2/5] Update AttachEffect.cpp --- src/Interop/AttachEffect.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Interop/AttachEffect.cpp b/src/Interop/AttachEffect.cpp index 3f037f33db..397f097014 100644 --- a/src/Interop/AttachEffect.cpp +++ b/src/Interop/AttachEffect.cpp @@ -38,15 +38,19 @@ int __stdcall AE_Attach( if (attachInfo.AttachTypes.empty()) return 0; - AEAttachParams params; - params.DurationOverride = durationOverride; - params.Delay = delay; - params.InitialDelay = initialDelay; - params.RecreationDelay = recreationDelay; + if (durationOverride != 0) + attachInfo.DurationOverrides.push_back(durationOverride); - int attachedCount = AttachEffectClass::Attach(pTargetTechno, pInvokerHouseClass, pInvokerTechno, pSourceAbs, attachInfo); + if (delay >= 0) + attachInfo.Delays.push_back(delay); - return attachedCount; + if (initialDelay >= 0) + attachInfo.InitialDelays.push_back(initialDelay); + + if (recreationDelay >= -1) + attachInfo.RecreationDelays.push_back(recreationDelay); + + return AttachEffectClass::Attach(pTargetTechno, pInvokerHouseClass, pInvokerTechno, pSourceAbs, attachInfo); } int __stdcall AE_Detach( From 13ae1a61b37fae8414b99924ffb19397633e76cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=88=AA=E5=91=B3=E9=BA=BB=E9=85=B1?= <93972760+TaranDahl@users.noreply.github.com> Date: Wed, 11 Mar 2026 09:33:40 +0800 Subject: [PATCH 3/5] update --- src/Interop/AttachEffect.cpp | 36 ++++++++++++------------------------ src/Interop/AttachEffect.h | 32 ++++++++++++++++++++++++-------- src/Interop/TechnoExt.cpp | 7 ++----- src/Interop/TechnoExt.h | 11 ++++++++++- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/Interop/AttachEffect.cpp b/src/Interop/AttachEffect.cpp index 397f097014..007f9d5045 100644 --- a/src/Interop/AttachEffect.cpp +++ b/src/Interop/AttachEffect.cpp @@ -4,10 +4,10 @@ #include "New/Type/AttachEffectTypeClass.h" int __stdcall AE_Attach( - void* pTarget, - void* pInvokerHouse, - void* pInvoker, - void* pSource, + TechnoClass* pTarget, + HouseClass* pInvokerHouse, + TechnoClass* pInvoker, + AbstractClass* pSource, const char** effectTypeNames, int typeCount, int durationOverride, @@ -19,11 +19,6 @@ int __stdcall AE_Attach( if (!pTarget || !effectTypeNames || typeCount <= 0) return 0; - TechnoClass* pTargetTechno = static_cast(pTarget); - HouseClass* pInvokerHouseClass = static_cast(pInvokerHouse); - TechnoClass* pInvokerTechno = static_cast(pInvoker); - AbstractClass* pSourceAbs = static_cast(pSource); - AEAttachInfoTypeClass attachInfo; for (int i = 0; i < typeCount; i++) @@ -50,11 +45,11 @@ int __stdcall AE_Attach( if (recreationDelay >= -1) attachInfo.RecreationDelays.push_back(recreationDelay); - return AttachEffectClass::Attach(pTargetTechno, pInvokerHouseClass, pInvokerTechno, pSourceAbs, attachInfo); + return AttachEffectClass::Attach(pTarget, pInvokerHouse, pInvoker, pSource, attachInfo); } int __stdcall AE_Detach( - void* pTarget, + TechnoClass* pTarget, const char** effectTypeNames, int typeCount ) @@ -62,8 +57,6 @@ int __stdcall AE_Detach( if (!pTarget || !effectTypeNames || typeCount <= 0) return 0; - TechnoClass* pTargetTechno = static_cast(pTarget); - AEAttachInfoTypeClass detachInfo; for (int i = 0; i < typeCount; i++) @@ -78,11 +71,11 @@ int __stdcall AE_Detach( if (detachInfo.RemoveTypes.empty()) return 0; - return AttachEffectClass::Detach(pTargetTechno, detachInfo); + return AttachEffectClass::Detach(pTarget, detachInfo); } int __stdcall AE_DetachByGroups( - void* pTarget, + TechnoClass* pTarget, const char** groupNames, int groupCount ) @@ -90,8 +83,6 @@ int __stdcall AE_DetachByGroups( if (!pTarget || !groupNames || groupCount <= 0) return 0; - TechnoClass* pTargetTechno = static_cast(pTarget); - AEAttachInfoTypeClass detachInfo; for (int i = 0; i < groupCount; i++) @@ -103,19 +94,16 @@ int __stdcall AE_DetachByGroups( if (detachInfo.RemoveGroups.empty()) return 0; - return AttachEffectClass::DetachByGroups(pTargetTechno, detachInfo); + return AttachEffectClass::DetachByGroups(pTarget, detachInfo); } void __stdcall AE_TransferEffects( - void* pSource, - void* pTarget + TechnoClass* pSource, + TechnoClass* pTarget ) { if (!pSource || !pTarget) return; - TechnoClass* pSourceTechno = static_cast(pSource); - TechnoClass* pTargetTechno = static_cast(pTarget); - - AttachEffectClass::TransferAttachedEffects(pSourceTechno, pTargetTechno); + AttachEffectClass::TransferAttachedEffects(pSource, pTarget); } diff --git a/src/Interop/AttachEffect.h b/src/Interop/AttachEffect.h index e746cb1b3d..95d2d8ac12 100644 --- a/src/Interop/AttachEffect.h +++ b/src/Interop/AttachEffect.h @@ -1,12 +1,19 @@ #pragma once +#include +#include +#include + extern "C" { + /// + /// Attaches AttachEffect instances to a target unit. + /// __declspec(dllexport) int __stdcall AE_Attach( - void* pTarget, - void* pInvokerHouse, - void* pInvoker, - void* pSource, + TechnoClass* pTarget, + HouseClass* pInvokerHouse, + TechnoClass* pInvoker, + AbstractClass* pSource, const char** effectTypeNames, int typeCount, int durationOverride, @@ -15,20 +22,29 @@ extern "C" int recreationDelay ); + /// + /// Removes AttachEffect instances matching given types from a unit. + /// __declspec(dllexport) int __stdcall AE_Detach( - void* pTarget, + TechnoClass* pTarget, const char** effectTypeNames, int typeCount ); + /// + /// Removes AttachEffect instances matching given groups from a unit. + /// __declspec(dllexport) int __stdcall AE_DetachByGroups( - void* pTarget, + TechnoClass* pTarget, const char** groupNames, int groupCount ); + /// + /// Transfers AttachEffect instances from one unit to another. + /// __declspec(dllexport) void __stdcall AE_TransferEffects( - void* pSource, - void* pTarget + TechnoClass* pSource, + TechnoClass* pTarget ); } diff --git a/src/Interop/TechnoExt.cpp b/src/Interop/TechnoExt.cpp index 349e8b7f23..959d9216e4 100644 --- a/src/Interop/TechnoExt.cpp +++ b/src/Interop/TechnoExt.cpp @@ -1,10 +1,7 @@ #include "TechnoExt.h" #include -extern "C" __declspec(dllexport) bool __stdcall ConvertToType_Phobos(void* pThis, void* toType) +extern "C" __declspec(dllexport) bool __stdcall ConvertToType_Phobos(FootClass* pThis, TechnoTypeClass* toType) { - auto pTechno = static_cast(pThis); - auto pType = static_cast(toType); - - return TechnoExt::ConvertToType(pTechno, pType); + return TechnoExt::ConvertToType(pThis, toType); } diff --git a/src/Interop/TechnoExt.h b/src/Interop/TechnoExt.h index 4e43272f41..90ec6c460e 100644 --- a/src/Interop/TechnoExt.h +++ b/src/Interop/TechnoExt.h @@ -1,6 +1,15 @@ #pragma once +#include +#include + extern "C" { - __declspec(dllexport) bool __stdcall ConvertToType_Phobos(void* pThis, void* toType); + /// + /// Converts a unit to a different type. + /// + /// Pointer to the FootClass instance to convert + /// Pointer to the target TechnoTypeClass + /// true if conversion was successful, false otherwise + __declspec(dllexport) bool __stdcall ConvertToType_Phobos(FootClass* pThis, TechnoTypeClass* toType); } From 3aefc461a48527375d388a7633a85116c3a3186d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=88=AA=E5=91=B3=E9=BA=BB=E9=85=B1?= <93972760+TaranDahl@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:16:26 +0800 Subject: [PATCH 4/5] Update README.md Co-authored-by: Noble Fish <89088785+DeathFishAtEase@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e184ce4c24..e99a76ab2c 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ This project was founded by [@Belonit](https://github.com/Belonit) (Gluk-v48) an ### Interoperability -Phobos has opened the external interfaces of some key components. If you are also developing your own engine extension and wish to use Phobos at the same time, please check out [Interop](./src/Interop). +Phobos has opened the external interfaces of some key components. If you are also developing your own engine extension and wish to use Phobos at the same time, please check out [Interop](https://github.com/Phobos-developers/Phobos/tree/develop/src/Interop). ### Maintenance crew From d77282bb170d33ba752af06ab6bf311afb79289a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=88=AA=E5=91=B3=E9=BA=BB=E9=85=B1?= <93972760+TaranDahl@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:16:42 +0800 Subject: [PATCH 5/5] Update docs/Whats-New.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/Whats-New.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Whats-New.md b/docs/Whats-New.md index cf58e68352..ad1c142a9d 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -545,7 +545,7 @@ New: - [Taunt warhead](New-or-Enhanced-Logics.md#taunt-warhead) (by TaranDahl) - [Custom hover vehicles shutdown drowning death](New-or-Enhanced-Logics.md#custom-hover-vehicles-shutdown-drowning-death) (by FlyStar) - [SHP turret vehicles support the use of `*tur.shp` files](New-or-Enhanced-Logics.md#independent-shp-vehicle-turret-files) (by FlyStar) -- [Export interface for external call](../README.md#interoperability) (by TaranDahl) +- [Export interface for external call](index.md#interoperability) (by TaranDahl) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)