Merge pull request 'feature/save-skill-combo' (#177) from feature/save-skill-combo into develop

Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/177
This commit is contained in:
haimh
2026-02-27 09:11:00 +00:00
24 changed files with 2714 additions and 179 deletions
@@ -0,0 +1,918 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1590197940424963217
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6666702292353843246}
- component: {fileID: 4026888369354985289}
m_Layer: 0
m_Name: DlgExit
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6666702292353843246
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1590197940424963217}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4878816101074468399}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &4026888369354985289
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1590197940424963217}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8ca9d1418c284fd395248056f086c7d4, type: 3}
m_Name:
m_EditorClassIdentifier:
ConfirmBtn: {fileID: 3576373828330281173}
CancelBtn: {fileID: 5816777684468032703}
--- !u!1 &1725743065086802770
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4878816101074468399}
- component: {fileID: 1101450299599105715}
- component: {fileID: 5337953600179164026}
m_Layer: 0
m_Name: Popup
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4878816101074468399
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1725743065086802770}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7913819123905793175}
- {fileID: 7527520206793245717}
- {fileID: 4965393937731457567}
- {fileID: 4000902174573487903}
m_Father: {fileID: 6666702292353843246}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 933.3333, y: 533.3333}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1101450299599105715
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1725743065086802770}
m_CullTransparentMesh: 1
--- !u!114 &5337953600179164026
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1725743065086802770}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 4744752b0496d42d0b1c52fcb705e044, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &4518958362188575915
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4965393937731457567}
- component: {fileID: 1891070853961845177}
- component: {fileID: 807580002560918717}
- component: {fileID: 3576373828330281173}
m_Layer: 0
m_Name: Button_Confirm
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4965393937731457567
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4518958362188575915}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4642911678502374063}
m_Father: {fileID: 4878816101074468399}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: -210, y: -150}
m_SizeDelta: {x: 313, y: 91}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1891070853961845177
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4518958362188575915}
m_CullTransparentMesh: 1
--- !u!114 &807580002560918717
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4518958362188575915}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: b545f49a479374ffaaec0c8f123b0c5f, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &3576373828330281173
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4518958362188575915}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 807580002560918717}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &4670976812881016521
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7913819123905793175}
- component: {fileID: 2369126678925736279}
- component: {fileID: 7564280183498118806}
m_Layer: 0
m_Name: Text (TMP)_Title
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7913819123905793175
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4670976812881016521}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4878816101074468399}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 1}
m_AnchorMax: {x: 0.5, y: 1}
m_AnchoredPosition: {x: -3.7721, y: -17.4557}
m_SizeDelta: {x: 298.0753, y: 34.9115}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2369126678925736279
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4670976812881016521}
m_CullTransparentMesh: 1
--- !u!114 &7564280183498118806
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4670976812881016521}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: "Th\xF4ng b\xE1o"
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 30
m_fontSizeBase: 30
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &5918190347695128963
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4642911678502374063}
- component: {fileID: 4834289956051303799}
- component: {fileID: 3482299799452283765}
m_Layer: 0
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4642911678502374063
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5918190347695128963}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4965393937731457567}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4834289956051303799
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5918190347695128963}
m_CullTransparentMesh: 1
--- !u!114 &3482299799452283765
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5918190347695128963}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: "X\xE1c nh\u1EADn"
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 50
m_fontSizeBase: 50
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &5923497699521027687
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4000902174573487903}
- component: {fileID: 7348237821025748982}
- component: {fileID: 356920440688922164}
- component: {fileID: 5816777684468032703}
m_Layer: 0
m_Name: Button_Cancel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4000902174573487903
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5923497699521027687}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1979839230795202451}
m_Father: {fileID: 4878816101074468399}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 210, y: -150}
m_SizeDelta: {x: 313, y: 91}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7348237821025748982
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5923497699521027687}
m_CullTransparentMesh: 1
--- !u!114 &356920440688922164
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5923497699521027687}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: b545f49a479374ffaaec0c8f123b0c5f, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &5816777684468032703
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5923497699521027687}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 356920440688922164}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &6076086137757476783
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7527520206793245717}
- component: {fileID: 717316905677608887}
- component: {fileID: 2182669632864579474}
m_Layer: 0
m_Name: Text (TMP)_Content
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7527520206793245717
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6076086137757476783}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4878816101074468399}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 1}
m_AnchorMax: {x: 0.5, y: 1}
m_AnchoredPosition: {x: -2, y: -201.94122}
m_SizeDelta: {x: 862.825, y: 279.6172}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &717316905677608887
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6076086137757476783}
m_CullTransparentMesh: 1
--- !u!114 &2182669632864579474
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6076086137757476783}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: "R\u1EDDi kh\u1ECFi ho\xE0n m\u1EF9 ?"
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 93.94
m_fontSizeBase: 93.94
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &8385824745593160430
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1979839230795202451}
- component: {fileID: 926584410341277518}
- component: {fileID: 7589457457506445651}
m_Layer: 0
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1979839230795202451
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8385824745593160430}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4000902174573487903}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &926584410341277518
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8385824745593160430}
m_CullTransparentMesh: 1
--- !u!114 &7589457457506445651
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8385824745593160430}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: "H\u1EE7y"
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 50
m_fontSizeBase: 50
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0c248d0510a114829b58d62d2ecc3b5e
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+155 -15
View File
@@ -38,15 +38,22 @@ namespace BrewMonster
public byte nLevel;
public byte nSight;
public byte nWaterEffect;
[MarshalAs(UnmanagedType.U1)]
public bool bSimpleTerrain;
public byte nTreeDetail;
public byte nGrassDetail;
public byte nCloudDetail;
[MarshalAs(UnmanagedType.U1)]
public bool bShadow;
[MarshalAs(UnmanagedType.U1)]
public bool bMipMapBias;
[MarshalAs(UnmanagedType.U1)]
public bool bFullGlow;
[MarshalAs(UnmanagedType.U1)]
public bool bSpaceWarp;
[MarshalAs(UnmanagedType.U1)]
public bool bSunFlare;
[MarshalAs(UnmanagedType.U1)]
public bool bAdvancedWater;
public byte nSoundVol;
public byte nMusicVol;
@@ -55,9 +62,13 @@ namespace BrewMonster
public int iRndHeight;
public int iTexDetail;
public int iSoundQuality;
[MarshalAs(UnmanagedType.U1)]
public bool bFullScreen;
[MarshalAs(UnmanagedType.U1)]
public bool bWideScreen;
[MarshalAs(UnmanagedType.U1)]
public bool bVSync;
[MarshalAs(UnmanagedType.U1)]
public bool bScaleUI;
public int iTheme;
@@ -124,35 +135,58 @@ namespace BrewMonster
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct EC_VIDEO_SETTING
{
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerHP;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerMP;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerEXP;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerHeadText;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerName;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerFaction;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerTitle;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerShop;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerSelfName;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerTalk;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerBubble;
[MarshalAs(UnmanagedType.U1)]
public bool bMonsterName;
[MarshalAs(UnmanagedType.U1)]
public bool bNPCName;
[MarshalAs(UnmanagedType.U1)]
public bool bGoodsName;
[MarshalAs(UnmanagedType.U1)]
public bool bModelLimit;
public byte nDistance;
[MarshalAs(UnmanagedType.U1)]
public bool bMapMonster;
[MarshalAs(UnmanagedType.U1)]
public bool bMapNPC;
[MarshalAs(UnmanagedType.U1)]
public bool bMapPlayer;
public byte nEffect;
[MarshalAs(UnmanagedType.U1)]
public bool bShowCustomize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_ConfigConstants.EC_COMBOSKILL_NUM)]
public EC_COMBOSKILL[] comboSkill;
[MarshalAs(UnmanagedType.U1)]
public bool bPlayerForce;
[MarshalAs(UnmanagedType.U1)]
public bool bMailToFriendsRemind;
public int iMailToFriendsCheckTime;
public char cTabSelType;
[MarshalAs(UnmanagedType.U1)]
public bool bActivityRemind;
public int ibActivityReminderCheckTime;
[MarshalAs(UnmanagedType.U1)]
public bool bCloseMeridiansHint;
public void Reset()
@@ -253,42 +287,94 @@ namespace BrewMonster
bCloseMeridiansHint = reader.ReadBoolean();
}
}
// Game Settings Structure
[StructLayout(LayoutKind.Sequential, Pack = 1)]
// CharSet.Ansi required so szAutoReply matches C++ ACHAR[65] (1 byte/char); default is Unicode (2 bytes/char).
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct EC_GAME_SETTING
{
[MarshalAs(UnmanagedType.U1)]
public bool bNoTeamRequest;
[MarshalAs(UnmanagedType.U1)]
public bool bNoTradeRequest;
[MarshalAs(UnmanagedType.U1)]
public bool bTurnaround;
[MarshalAs(UnmanagedType.U1)]
public bool bReverseWheel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_ConfigConstants.EC_USERCHANNEL_NUM * 15)] // GP_CHAT_MAX = 15
public bool[] bChannel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_ConfigConstants.EC_USERCHANNEL_NUM * 15, ArraySubType = UnmanagedType.I1)] // GP_CHAT_MAX = 15; I1 = 1 byte per bool to match C++ bool[6][15]
public byte[] bChannel; // I can't use bool[] here because C# bool is 1 byte but C++ bool is also 1 byte, so we use byte[] to match the size and layout of the original C++ struct.
[MarshalAs(UnmanagedType.U1)]
public bool bAutoReply;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = EC_ConfigConstants.EC_AUTOREPLY_LEN + 1)]
public string szAutoReply;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_ConfigConstants.EC_AUTOREPLY_LEN + 1)]
public ushort[] szAutoReply; // Using ushort[] to match C++ ACHAR[65] (1 byte/char) with CharSet.Ansi; we will convert to string when reading/writing.
/// <summary>Convert szAutoReply buffer (UTF-8 bytes stored as ushort) to string.</summary>
public static string SzAutoReplyToString(ushort[] buf)
{
if (buf == null || buf.Length == 0) return string.Empty;
int n = 0;
while (n < buf.Length && buf[n] != 0) n++;
if (n == 0) return string.Empty;
var bytes = new byte[n];
for (int i = 0; i < n; i++) bytes[i] = (byte)buf[i];
return Encoding.UTF8.GetString(bytes);
}
/// <summary>Write string into szAutoReply buffer as null-terminated UTF-8 (each byte stored as ushort).</summary>
public static void StringToSzAutoReply(string s, ushort[] buf)
{
if (buf == null || buf.Length == 0) return;
int maxLen = Math.Min(EC_ConfigConstants.EC_AUTOREPLY_LEN, buf.Length - 1);
byte[] bytes = Encoding.UTF8.GetBytes(s ?? string.Empty);
int n = Math.Min(bytes.Length, maxLen);
for (int i = 0; i < n; i++) buf[i] = bytes[i];
buf[n] = 0;
for (int i = n + 1; i < buf.Length; i++) buf[i] = 0;
}
[MarshalAs(UnmanagedType.U1)]
public float fCamTurnSpeed;
public float fCamZoomSpeed;
public byte nFontSize;
[MarshalAs(UnmanagedType.U1)]
public bool bAtk_Player;
[MarshalAs(UnmanagedType.U1)]
public bool bAtk_NoMafia;
[MarshalAs(UnmanagedType.U1)]
public bool bAtk_NoWhite;
[MarshalAs(UnmanagedType.U1)]
public bool bFontBold;
[MarshalAs(UnmanagedType.U1)]
public bool bBls_NoRed;
[MarshalAs(UnmanagedType.U1)]
public bool bBls_NoMafia;
[MarshalAs(UnmanagedType.U1)]
public bool bBls_Self;
[MarshalAs(UnmanagedType.U1)]
public bool bBlsRefuse_Neutral;
[MarshalAs(UnmanagedType.U1)]
public bool bHideAutoGuide;
[MarshalAs(UnmanagedType.U1)]
public bool bAtk_NoAlliance;
[MarshalAs(UnmanagedType.U1)]
public bool bBls_NoAlliance;
[MarshalAs(UnmanagedType.U1)]
public bool bBlsRefuse_NonTeammate;
[MarshalAs(UnmanagedType.U1)]
public bool bAtk_NoForce;
[MarshalAs(UnmanagedType.U1)]
public bool bBls_NoForce;
[MarshalAs(UnmanagedType.U1)]
public bool bLockQuickBar;
[MarshalAs(UnmanagedType.U1)]
public bool bPetAutoSkill;
[MarshalAs(UnmanagedType.U1)]
public bool bAutoTeamForTask;
[MarshalAs(UnmanagedType.U1)]
public bool bDisableAutoWikiHelp;
[MarshalAs(UnmanagedType.U1)]
public bool bExclusiveAwardMode;
[MarshalAs(UnmanagedType.U1)]
public bool bHideIceThunderBall;
public void Reset()
@@ -298,7 +384,7 @@ namespace BrewMonster
bTurnaround = false;
bReverseWheel = false;
bAutoReply = false;
szAutoReply = "";
szAutoReply = new ushort[EC_ConfigConstants.EC_AUTOREPLY_LEN + 1]; // empty string (first byte 0)
fCamTurnSpeed = 10.0f;
fCamZoomSpeed = 1.0f;
nFontSize = 2;
@@ -324,7 +410,7 @@ namespace BrewMonster
bHideIceThunderBall = false;
// Initialize channel array with default values
bChannel = new bool[EC_ConfigConstants.EC_USERCHANNEL_NUM * 15];
bChannel = new byte[EC_ConfigConstants.EC_USERCHANNEL_NUM * 15];
bool[,] a_bChannel = new bool[,]
{
{ true, true, true, true, true, false, false, true, true, true, false, true, true, true, true },
@@ -339,7 +425,7 @@ namespace BrewMonster
{
for (int j = 0; j < 15; j++)
{
bChannel[i * 15 + j] = a_bChannel[i, j];
bChannel[i * 15 + j] = (byte)(a_bChannel[i, j] ? 1 : 0);
}
}
}
@@ -359,7 +445,7 @@ namespace BrewMonster
{
for (int i = 0; i < EC_ConfigConstants.EC_USERCHANNEL_NUM * 15; i++)
{
bChannel[i] = reader.ReadBoolean();
bChannel[i] = (byte)(reader.ReadBoolean() ? 1 : 0);
}
}
else if (dwVer >= 26)
@@ -367,7 +453,7 @@ namespace BrewMonster
for (int i = 0; i < EC_ConfigConstants.EC_USERCHANNEL_NUM * 14; i++)
{
if (i < bChannel.Length)
bChannel[i] = reader.ReadBoolean();
bChannel[i] = (byte)(reader.ReadBoolean() ? 1 : 0);
}
}
else
@@ -375,12 +461,17 @@ namespace BrewMonster
for (int i = 0; i < EC_ConfigConstants.EC_USERCHANNEL_NUM * 13; i++)
{
if (i < bChannel.Length)
bChannel[i] = reader.ReadBoolean();
bChannel[i] = (byte)(reader.ReadBoolean() ? 1 : 0);
}
}
bAutoReply = reader.ReadBoolean();
szAutoReply = Encoding.UTF8.GetString(reader.ReadBytes(EC_ConfigConstants.EC_AUTOREPLY_LEN + 1)).TrimEnd('\0');
// Binary format: 65 bytes UTF-8; store each byte in ushort[] for struct layout
if (szAutoReply == null || szAutoReply.Length < EC_ConfigConstants.EC_AUTOREPLY_LEN + 1)
szAutoReply = new ushort[EC_ConfigConstants.EC_AUTOREPLY_LEN + 1];
byte[] autoReplyBytes = reader.ReadBytes(EC_ConfigConstants.EC_AUTOREPLY_LEN + 1);
for (int i = 0; i < autoReplyBytes.Length; i++)
szAutoReply[i] = autoReplyBytes[i];
fCamTurnSpeed = reader.ReadSingle();
fCamZoomSpeed = reader.ReadSingle();
nFontSize = reader.ReadByte();
@@ -472,6 +563,7 @@ namespace BrewMonster
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ITEM_GROUP
{
[MarshalAs(UnmanagedType.U1)]
public bool enable;
public int item;
public sbyte percent;
@@ -701,7 +793,9 @@ namespace BrewMonster
public uint m_dwDefAmbient;
// Test code, temporary parameters
[MarshalAs(UnmanagedType.U1)]
public bool m_bShowForest = true;
[MarshalAs(UnmanagedType.U1)]
public bool m_bShowGrassLand = true;
// Configs user cannot change
@@ -721,32 +815,48 @@ namespace BrewMonster
private string m_strWindowsTitle = "Element Client";
private string m_strMiniDLTitle = "";
private int m_iClientID = -1;
[MarshalAs(UnmanagedType.U1)]
private bool m_bRegisterUIScriptFunc = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bEnableGT = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bEnableArc = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bEnableArcAsia = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bMiniClient = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bSendLogicCheckInfo = false;
private List<string> m_strThemeFiles = new List<string>();
// DEBUG only settings
[MarshalAs(UnmanagedType.U1)]
private bool m_bConsole = false;
private int m_iRTDebug = 1;
[MarshalAs(UnmanagedType.U1)]
private bool m_bShowNPCID = false;
private float m_fRunSpeed = 5.0f;
private float m_fWalkSpeed = 2.0f;
[MarshalAs(UnmanagedType.U1)]
private bool m_bTestDist = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bShowPos = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bGameStat = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bShowID = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bSkipFrame = false;
[MarshalAs(UnmanagedType.U1)]
private bool m_bModelUpt = true;
[MarshalAs(UnmanagedType.U1)]
private bool m_bDebugFog = false;
private float m_fDebugFogStart = 10.0f;
private float m_fDebugFogEnd = 100.0f;
private float m_fDebugFogDensity = 0.5f;
private uint m_dwDebugFogColor = 0xFFFFFFFF;
[MarshalAs(UnmanagedType.U1)]
private bool m_bAdjusting = false;
// User settings
@@ -1063,6 +1173,32 @@ namespace BrewMonster
return true;
}
/// <summary>
/// Write user config data into buffer at given offset. 在指定偏移处写入用户配置数据。
/// </summary>
public bool SaveUserConfigData(byte[] pDataBuf, int startIndex, out int piSize)
{
if (startIndex < 0) { piSize = 0; return false; }
piSize = 0;
int iTotalSize = 0;
iTotalSize += sizeof(uint);
iTotalSize += Marshal.SizeOf(typeof(EC_VIDEO_SETTING));
iTotalSize += Marshal.SizeOf(typeof(EC_GAME_SETTING));
iTotalSize += Marshal.SizeOf(typeof(EC_BLACKLIST_SETTING));
iTotalSize += Marshal.SizeOf(typeof(EC_COMPUTER_AIDED_SETTING));
if (pDataBuf != null && startIndex + iTotalSize <= pDataBuf.Length)
{
using (MemoryStream ms = new MemoryStream(pDataBuf, startIndex, pDataBuf.Length - startIndex))
using (BinaryWriter writer = new BinaryWriter(ms))
{
writer.Write((uint)EC_ConfigConstants.EC_CONFIG_VERSION);
}
}
piSize = iTotalSize;
return true;
}
public void DefaultUserConfigData()
{
DefaultUserSettings(ref m_ss, ref m_vs, ref m_gs, ref m_bs, ref m_cas);
@@ -1246,9 +1382,12 @@ namespace BrewMonster
private void Verify()
{
// Verify game setting
if (m_gs.szAutoReply != null && m_gs.szAutoReply.Length > EC_ConfigConstants.EC_AUTOREPLY_LEN)
string autoReplyStr = EC_GAME_SETTING.SzAutoReplyToString(m_gs.szAutoReply);
if (autoReplyStr.Length > EC_ConfigConstants.EC_AUTOREPLY_LEN)
{
m_gs.szAutoReply = m_gs.szAutoReply.Substring(0, EC_ConfigConstants.EC_AUTOREPLY_LEN);
if (m_gs.szAutoReply == null || m_gs.szAutoReply.Length < EC_ConfigConstants.EC_AUTOREPLY_LEN + 1)
m_gs.szAutoReply = new ushort[EC_ConfigConstants.EC_AUTOREPLY_LEN + 1];
EC_GAME_SETTING.StringToSzAutoReply(autoReplyStr.Substring(0, EC_ConfigConstants.EC_AUTOREPLY_LEN), m_gs.szAutoReply);
}
if (m_gs.nFontSize > 4)
@@ -1347,6 +1486,7 @@ namespace BrewMonster
public void SaveBlockedID()
{
// TODO
// Note: Would need character ID
// string strDir = Path.Combine(Application.persistentDataPath, "userdata", "blacklist");
// Directory.CreateDirectory(strDir);
@@ -0,0 +1,314 @@
// Filename : EC_PendingAction.cs
// Creator : Xu Wenbin
// Date : 2011/11/09
// Converted from C++: EC_PendingAction.cpp / EC_PendingAction.h
using System.Collections.Generic;
using BrewMonster;
using BrewMonster.Network;
using BrewMonster.UI;
using CSNetwork;
using UnityEngine;
// Logout type constants (C++: gnetdef.h)
// _PLAYER_LOGOUT_FULL 0, _PLAYER_LOGOUT_HALF 1
public static class PendingActionConstants
{
public const int _PLAYER_LOGOUT_FULL = 0;
public const int _PLAYER_LOGOUT_HALF = 1;
}
// CECPendingAction — base class for delayed/pending actions
public abstract class CECPendingAction
{
// 执行的时限 / Execution time limit
private readonly CECCounter m_Counter;
// 是否还需要执行 / Whether still needs to execute
private bool m_bNeedExecute;
// 是否收到外界执行指示 / Whether received external execute trigger
private bool m_bTriggered;
// 执行结果:是否成功执行 / Execute result: whether executed successfully
private bool m_bExecuteResult;
public CECPendingAction(uint dwTimerPeriod)
{
m_Counter = new CECCounter();
m_Counter.SetPeriod((float)dwTimerPeriod);
m_bNeedExecute = true;
m_bTriggered = false;
m_bExecuteResult = false;
}
public void Update(uint dwElapsedTime)
{
if (GetNeedExecute())
{
// 每次都尝试执行 / Try execute every time
if (m_Counter.IncCounter((float)dwElapsedTime))
{
// 计时器到 / Timer reached
// 强制执行 / Force execute
m_bExecuteResult = Execute();
// 不需要再进行尝试 / No need to try again
m_bNeedExecute = false;
}
// else 计时中 / else counting
}
}
public void Trigger()
{
if (!GetNeedExecute())
{
// 计时器已经强制执行,不需要再触发执行 / Timer already forced execute, no need to trigger again
return;
}
if (GetTriggered())
{
// 不允许多次触发 / Multiple trigger not allowed
return;
}
m_bTriggered = true;
m_bExecuteResult = Execute();
m_bNeedExecute = false;
}
public bool GetNeedExecute() => m_bNeedExecute;
public bool GetTriggered() => m_bTriggered;
public abstract string GetName();
protected abstract bool Execute();
// Whether currently in game (session connected, game state in-game, host ready)
protected bool IsInGame()
{
var pSession = GetGameSession();
var pGameRun = GetGameRun();
var pHost = pGameRun?.GetHostPlayer();
return pSession != null
&& pSession.IsConnected
&& pGameRun != null
&& pGameRun.GetGameState() == (int)GameState.GS_GAME
&& pHost != null
&& pHost.HostIsReady();
}
protected static CECGameRun GetGameRun() => EC_Game.GetGameRun();
protected static GameSession GetGameSession() => UnityGameSession.Instance?.GameSession;
protected static CECHostPlayer GetHostPlayer() => GetGameRun()?.GetHostPlayer();
}
// 游戏小退 / Game logout (half — back to select role)
public class CECPendingLogoutHalf : CECPendingAction
{
public CECPendingLogoutHalf(uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { }
protected override bool Execute()
{
bool bSuccess = false;
if (IsInGame())
{
GetGameSession().SendPlayerLogout(PendingActionConstants._PLAYER_LOGOUT_HALF);
bSuccess = true;
}
return bSuccess;
}
public override string GetName() => "CECPendingLogoutHalf";
}
// 游戏大退 / Game logout (full — account logout)
public class CECPendingLogoutFull : CECPendingAction
{
public CECPendingLogoutFull(uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { }
protected override bool Execute()
{
bool bSuccess = false;
if (IsInGame())
{
GetGameSession().SendPlayerLogout(PendingActionConstants._PLAYER_LOGOUT_FULL);
bSuccess = true;
}
return bSuccess;
}
public override string GetName() => "CECPendingLogoutFull";
}
// 寄售角色 / Selling role
public class CECPendingSellingRole : CECPendingAction
{
public CECPendingSellingRole(uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { }
protected override bool Execute()
{
bool bSuccess = false;
if (IsInGame())
{
GetGameSession().SendPlayerLogout(PendingActionConstants._PLAYER_LOGOUT_HALF);
GetGameRun().SetSellingRoleID(GetHostPlayer().GetCharacterID());
bSuccess = true;
}
return bSuccess;
}
public override string GetName() => "CECPendingSellingRole";
}
// 跨服小退 / Cross-server logout (half)
public class CECPendingLogoutCrossServer : CECPendingAction
{
public CECPendingLogoutCrossServer(uint dwTimerPeriod = 5000) : base(dwTimerPeriod) { }
protected override bool Execute()
{
GetGameRun().SetLogoutFlag(2);
return true;
}
public override string GetName() => "CECPendingLogoutCrossServer";
}
// 进出跨服 / Cross-server get in or out
// m_bGetIn: 进入跨服时为 true;否则为 false / true when entering cross-server; otherwise false
public class CECPendingCrossServerGetInOut : CECPendingAction
{
private readonly bool m_bGetIn;
public CECPendingCrossServerGetInOut(bool bGetIn, uint dwTimerPeriod = 5000)
: base(dwTimerPeriod)
{
m_bGetIn = bGetIn;
}
protected override bool Execute()
{
bool bSuccess = false;
if (IsInGame())
{
var session = GetGameSession();
if (session != null)
{
if (m_bGetIn)
session.c2s_CmdNPCSevCrossServerGetIn();
else
session.c2s_CmdNPCSevCrossServerGetOut();
}
}
var pGameUIMan = GetGameRun()?.GetUIManager()?.GetInGameUIMan();
if (pGameUIMan is CECGameUIMan inGameUIMan)
inGameUIMan.EndNPCService();
return bSuccess;
}
public override string GetName() => "CECPendingCrossServerGetInOut";
}
// CECPendingActionArray — container for multiple pending actions
public class CECPendingActionArray
{
private readonly List<CECPendingAction> m_actions = new List<CECPendingAction>();
private bool m_bAllowMultiActions;
public CECPendingActionArray(bool bAllowMultiActions)
{
m_bAllowMultiActions = bAllowMultiActions;
}
~CECPendingActionArray()
{
Clear();
}
public void Append(CECPendingAction pAction)
{
// 添加新事件 / Add new event
if (pAction == null)
{
Debug.Assert(false);
return;
}
if (!pAction.GetNeedExecute())
{
Debug.Assert(false);
return;
}
if (!GetAllowMultiAction())
Clear();
m_actions.Add(pAction);
}
public void AppendForSaveConfig(CECPendingAction pAction)
{
if (pAction == null)
{
Debug.Assert(false);
return;
}
if (!pAction.GetNeedExecute())
{
Debug.Assert(false);
return;
}
uint saveResult = EC_Game.GetGameRun().SaveConfigsToServer();
if (saveResult != 2)
{
pAction.Trigger();
return;
}
Append(pAction);
}
public void Update(uint dwElapsedTime)
{
if (m_actions.Count == 0) return;
for (int i = m_actions.Count - 1; i >= 0; i--)
{
CECPendingAction pAction = m_actions[i];
pAction.Update(dwElapsedTime);
if (!pAction.GetNeedExecute())
{
m_actions.RemoveAt(i);
}
}
}
public void TriggerAll()
{
if (m_actions.Count == 0) return;
foreach (var pAction in m_actions)
{
if (pAction.GetNeedExecute())
pAction.Trigger();
}
}
public void Clear()
{
// 清除当前所有事件 / Clear all current events
if (m_actions.Count == 0) return;
m_actions.Clear();
}
public void SetAllowMultiAction(bool bAllow)
{
if (GetAllowMultiAction() == bAllow) return;
m_bAllowMultiActions = bAllow;
// 按时间先后顺序,只保留队列最后一个 / By time order, keep only the last one in queue
if (!bAllow && m_actions.Count > 1)
{
var last = m_actions[m_actions.Count - 1];
m_actions.Clear();
m_actions.Add(last);
}
}
public bool GetAllowMultiAction() => m_bAllowMultiActions;
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a8fc69213d734cb49b1b381a760ae418
timeCreated: 1770180043
@@ -0,0 +1,84 @@
using System;
using System.Runtime.InteropServices;
using EditorAttributes;
// using NaughtyAttributes;
using UnityEngine;
namespace BrewMonster
{
public class TestByteNumber : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
[ContextMenu("Test")]
public void Test()
{
var origin = Marshal.SizeOf<EC_COMPUTER_AIDED_SETTING>();
var diff = Marshal.SizeOf<EC_GAME_SETTING>() - Marshal.SizeOf<EC_GAME_SETTING_TEST>();
BMLogger.Log($" Origin : {origin } - diff = {diff}"); // 255
}
[ContextMenu(" TestCompress")]
public void TestCompress()
{
int value = 123456;
byte[] src = BitConverter.GetBytes(value);
int dstLen = 10000;
byte[] dst = new byte[dstLen];
int res = AFilePackage.Compress( src, 0, src.Length, dst, 0, ref dstLen);
BMLogger.Log($" Res : {res} - srcLen = {src.Length} - dstLen = {dstLen} - compressed data: {BitConverter.ToString(dst, 0, dstLen)}");
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct EC_GAME_SETTING_TEST
{
[MarshalAs(UnmanagedType.U1)] public bool bNoTeamRequest;
[MarshalAs(UnmanagedType.U1)] public bool bNoTradeRequest;
[MarshalAs(UnmanagedType.U1)] public bool bTurnaround;
[MarshalAs(UnmanagedType.U1)] public bool bReverseWheel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_ConfigConstants.EC_USERCHANNEL_NUM * 15,
ArraySubType = UnmanagedType.I1)] // GP_CHAT_MAX = 15; I1 = 1 byte per bool to match C++ bool[6][15]
public byte[] bChannel;
[MarshalAs(UnmanagedType.U1)]
public bool bAutoReply;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = EC_ConfigConstants.EC_AUTOREPLY_LEN + 1)]
public string szAutoReply;
[MarshalAs(UnmanagedType.U1)] public float fCamTurnSpeed;
public float fCamZoomSpeed;
public byte nFontSize;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_Player;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_NoMafia;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_NoWhite;
[MarshalAs(UnmanagedType.U1)] public bool bFontBold;
[MarshalAs(UnmanagedType.U1)] public bool bBls_NoRed;
[MarshalAs(UnmanagedType.U1)] public bool bBls_NoMafia;
[MarshalAs(UnmanagedType.U1)] public bool bBls_Self;
[MarshalAs(UnmanagedType.U1)] public bool bBlsRefuse_Neutral;
[MarshalAs(UnmanagedType.U1)] public bool bHideAutoGuide;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_NoAlliance;
[MarshalAs(UnmanagedType.U1)] public bool bBls_NoAlliance;
[MarshalAs(UnmanagedType.U1)] public bool bBlsRefuse_NonTeammate;
[MarshalAs(UnmanagedType.U1)] public bool bAtk_NoForce;
[MarshalAs(UnmanagedType.U1)] public bool bBls_NoForce;
[MarshalAs(UnmanagedType.U1)] public bool bLockQuickBar;
[MarshalAs(UnmanagedType.U1)] public bool bPetAutoSkill;
[MarshalAs(UnmanagedType.U1)] public bool bAutoTeamForTask;
[MarshalAs(UnmanagedType.U1)] public bool bDisableAutoWikiHelp;
[MarshalAs(UnmanagedType.U1)] public bool bExclusiveAwardMode;
[MarshalAs(UnmanagedType.U1)] public bool bHideIceThunderBall;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 67551ceb317224e67b8140cbe7175c44
@@ -60,7 +60,7 @@ namespace BrewMonster.Scripts.Managers
}
}
public void Resize(int iNewSize)
public virtual void Resize(int iNewSize)
{
int oldSize = m_aItems.Length;
if (iNewSize < 0) iNewSize = 0;
@@ -1518,6 +1518,27 @@ namespace CSNetwork
p.Roleid = m_iCharID;
SendProtocol(p);
}
/// <summary>
/// Save config data to server (sends setuiconfig with compressed config blob).
/// 保存配置数据到服务器(发送 setuiconfig 及压缩后的配置数据)。
/// </summary>
public void SaveConfigData(byte[] pBuf, int len)
{
BMLogger.Log($"[MH] Session.SaveConfigData | len={len}");
if (pBuf == null || len <= 0) return;
var p = new setuiconfig();
p.Roleid = m_iCharID;
p.Localsid = (int)_localsid;
byte[] slice = new byte[len];
Buffer.BlockCopy(pBuf, 0, slice, 0, len);
p.Ui_config = new Octets(slice);
// return;
SendProtocol(p);
}
private void SetCharacterID(int iCharID)
{
m_iCharID = iCharID;
@@ -2000,5 +2021,17 @@ namespace CSNetwork
gamedatasend.Data = C2SCommandFactory.CreateNPCSevHatchPetCmd(iIvtrIdx, idEgg);
SendProtocol(gamedatasend);
}
// Cross-server get in (C++: c2s_CmdNPCSevCrossServerGetIn) — TODO: implement C2S packet when needed
public void c2s_CmdNPCSevCrossServerGetIn()
{
// TODO: C2SCommandFactory.CreateNPCSevCrossServerGetInCmd() and SendProtocol
}
// Cross-server get out (C++: c2s_CmdNPCSevCrossServerGetOut) — TODO: implement C2S packet when needed
public void c2s_CmdNPCSevCrossServerGetOut()
{
// TODO: C2SCommandFactory.CreateNPCSevCrossServerGetOutCmd() and SendProtocol
}
}
}
@@ -168,21 +168,21 @@ namespace BrewMonster
/// <summary>
/// Create an auto fashion shortcut at specified position
/// </summary>
/* public bool CreateAutoFashionShortcut(int iSlot, int iFashionIdx)
{
CECSCAutoFashion pAutoFashionSC = new CECSCAutoFashion();
if (pAutoFashionSC == null)
return false;
if (!pAutoFashionSC.Init(iFashionIdx))
{
Debug.LogError("CECShortcutSet::CreateAutoFashionShortcut, Failed to initialize auto fashion shortcut");
return false;
}
SetShortcut(iSlot, pAutoFashionSC);
return true;
}
// public bool CreateAutoFashionShortcut(int iSlot, int iFashionIdx)
// {
// CECSCAutoFashion pAutoFashionSC = new CECSCAutoFashion();
// if (pAutoFashionSC == null)
// return false;
//
// if (!pAutoFashionSC.Init(iFashionIdx))
// {
// Debug.LogError("CECShortcutSet::CreateAutoFashionShortcut, Failed to initialize auto fashion shortcut");
// return false;
// }
//
// SetShortcut(iSlot, pAutoFashionSC);
// return true;
// }
/// <summary>
/// Create a system module shortcut at specified position
@@ -201,7 +201,7 @@ namespace BrewMonster
SetShortcut(iSlot, pSysModule);
return true;
}*/
}
/// <summary>
/// Duplicate a shortcut to specified position
@@ -495,7 +495,10 @@ namespace BrewMonster
// Record shortcut's position and type
data.AddRange(BitConverter.GetBytes(i));
data.AddRange(BitConverter.GetBytes((int)pSC.GetType()));
BMLogger.Log($"[MH] Saving shortcut slot: {i} Type: {pSC.GetType()}");
// TODO: implement other shortcut types
switch ((CECShortcut.ShortcutType)pSC.GetType())
{
/* case CECShortcut.ShortcutType.SCT_COMMAND:
@@ -513,45 +516,45 @@ namespace BrewMonster
break;
}
/* case CECShortcut.ShortcutType.SCT_ITEM:
{
CECSCItem itemSC = (CECSCItem)pSC;
data.AddRange(BitConverter.GetBytes(itemSC.GetInventory()));
data.AddRange(BitConverter.GetBytes(itemSC.GetIvtrSlot()));
data.AddRange(BitConverter.GetBytes(itemSC.GetItemTID()));
break;
}
// case CECShortcut.ShortcutType.SCT_ITEM:
// {
// CECSCItem itemSC = (CECSCItem)pSC;
// data.AddRange(BitConverter.GetBytes(itemSC.GetInventory()));
// data.AddRange(BitConverter.GetBytes(itemSC.GetIvtrSlot()));
// data.AddRange(BitConverter.GetBytes(itemSC.GetItemTID()));
// break;
// }
case CECShortcut.ShortcutType.SCT_SKILLGRP:
{
CECSCSkillGrp skillGrpSC = (CECSCSkillGrp)pSC;
data.AddRange(BitConverter.GetBytes(skillGrpSC.GetGroupIndex()));
break;
}
case CECShortcut.ShortcutType.SCT_SKILLGRP:
{
CECSCSkillGrp skillGrpSC = (CECSCSkillGrp)pSC;
data.AddRange(BitConverter.GetBytes(skillGrpSC.GetGroupIndex()));
break;
}
case CECShortcut.ShortcutType.SCT_PET:
{
CECSCPet petSC = (CECSCPet)pSC;
data.AddRange(BitConverter.GetBytes(petSC.GetPetIndex()));
break;
}
// case CECShortcut.ShortcutType.SCT_PET:
// {
// CECSCPet petSC = (CECSCPet)pSC;
// data.AddRange(BitConverter.GetBytes(petSC.GetPetIndex()));
// break;
// }
//
// case CECShortcut.ShortcutType.SCT_AUTOFASHION:
// {
// CECSCAutoFashion fashionSC = (CECSCAutoFashion)pSC;
// data.AddRange(BitConverter.GetBytes(fashionSC.GetAutoFashionIndex()));
// break;
// }
case CECShortcut.ShortcutType.SCT_AUTOFASHION:
{
CECSCAutoFashion fashionSC = (CECSCAutoFashion)pSC;
data.AddRange(BitConverter.GetBytes(fashionSC.GetAutoFashionIndex()));
break;
}
case CECShortcut.ShortcutType.SCT_SYSMODULE:
{
CECSCSysModule sysSC = (CECSCSysModule)pSC;
data.AddRange(BitConverter.GetBytes(sysSC.GetSysModID()));
break;
}*/
case CECShortcut.ShortcutType.SCT_SYSMODULE:
{
CECSCSysModule sysSC = (CECSCSysModule)pSC;
data.AddRange(BitConverter.GetBytes(sysSC.GetSysModID()));
break;
}
default:
Debug.LogError("CECShortcutSet::SaveConfigData - Unknown shortcut type");
Debug.LogError($"CECShortcutSet::SaveConfigData - Unknown shortcut type = { pSC.GetType()}");
break;
}
}
@@ -587,6 +590,8 @@ namespace BrewMonster
int iSCType = GPDataTypeHelper.FromBytes<int>(pDataBuf, offset);
offset += sizeof(int);
BMLogger.Log("[MH] Loading shortcut slot: " + iSlot + " Type: " + iSCType);
switch ((CECShortcut.ShortcutType)iSCType)
{
@@ -679,41 +684,41 @@ namespace BrewMonster
break;
}
/*case CECShortcut.ShortcutType.SCT_PET:
{
if (dwVer >= 4)
{
int iPetIndex = BitConverter.ToInt32(pDataBuf, offset);
offset += sizeof(int);
if (iPetIndex >= 0)
CreatePetShortcut(iSlot, iPetIndex);
}
else
{
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for pet");
return false;
}
break;
}
case CECShortcut.ShortcutType.SCT_AUTOFASHION:
{
if (dwVer >= 5)
{
int iAutoFashionIndex = BitConverter.ToInt32(pDataBuf, offset);
offset += sizeof(int);
if (iAutoFashionIndex >= 0)
CreateAutoFashionShortcut(iSlot, iAutoFashionIndex);
}
else
{
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for auto fashion");
return false;
}
break;
}
// case CECShortcut.ShortcutType.SCT_PET:
// {
// if (dwVer >= 4)
// {
// int iPetIndex = BitConverter.ToInt32(pDataBuf, offset);
// offset += sizeof(int);
//
// if (iPetIndex >= 0)
// CreatePetShortcut(iSlot, iPetIndex);
// }
// else
// {
// Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for pet");
// return false;
// }
// break;
// }
//
// case CECShortcut.ShortcutType.SCT_AUTOFASHION:
// {
// if (dwVer >= 5)
// {
// int iAutoFashionIndex = BitConverter.ToInt32(pDataBuf, offset);
// offset += sizeof(int);
//
// if (iAutoFashionIndex >= 0)
// CreateAutoFashionShortcut(iSlot, iAutoFashionIndex);
// }
// else
// {
// Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for auto fashion");
// return false;
// }
// break;
// }
case CECShortcut.ShortcutType.SCT_SYSMODULE:
{
@@ -731,7 +736,7 @@ namespace BrewMonster
return false;
}
break;
}*/
}
/* default:
//TODO: uncomment
@@ -1167,6 +1172,98 @@ namespace BrewMonster
{
public CECSkill GetSkillByID(int id) => null;
}*/
// class CECSCSysModule : public CECShortcut
public class CECSCSysModule : CECShortcut
{
// public: // Types
// enum { FM_NONE = -1, FM_GT, FM_TOUCH, ... FM_NUM, };
public enum SysModuleType
{
FM_NONE = -1,
FM_GT,
FM_TOUCH,
FM_ROBOT, // 帮派系统 (Faction / Guild system)
FM_WIKI,
FM_OFFLINESHOP, // 摆摊 (Offline shop / Stall)
FM_BORADCAST, // 广播系统 (Broadcast system)
FM_MATCH, // 边缘系统 (Match system)
FM_ADDEXP, // 帮会系统 (Guild / Add exp system)
FM_AUTOHPMP, // 辅助功能,自动加药 (Auxiliary function, auto potion)
FM_NUM,
}
// public: // Attributes
// static const int g_SysIndexMap[FM_NUM];
public static readonly int[] g_SysIndexMap = new int[(int)SysModuleType.FM_NUM];
// protected: // Attributes
// ACString m_strDesc;
protected string m_strDesc;
// char m_IconFile[256];
protected string m_IconFile;
// int m_iSystem; // system ID
protected int m_iSystem;
// public: // Constructor and Destructor
// CECSCSysModule();
public CECSCSysModule()
{
m_iSCType = (int)ShortcutType.SCT_SYSMODULE;
m_strDesc = string.Empty;
m_IconFile = string.Empty;
m_iSystem = (int)SysModuleType.FM_NONE;
}
// CECSCSysModule(const CECSCSysModule& src);
public CECSCSysModule(CECSCSysModule src)
{
m_iSCType = src.m_iSCType;
m_strDesc = src.m_strDesc;
m_IconFile = src.m_IconFile;
m_iSystem = src.m_iSystem;
}
// virtual ~CECSCSysModule() {}
// (no destructor in C#)
// bool Init(int iSys);
public bool Init(int iSys)
{
m_iSystem = iSys;
// TODO: load m_strDesc and m_IconFile from config/table by iSys if needed
return true;
}
// virtual CECShortcut* Clone();
public override CECShortcut Clone()
{
return new CECSCSysModule(this);
}
// virtual bool Execute();
public override bool Execute()
{
// TODO: open corresponding system UI by m_iSystem (e.g. GT, Touch, Robot, Wiki, OfflineShop, Broadcast, Match, AddExp, AutoHpMp)
return true;
}
// int GetSysModID() const { return m_iSystem; }
public int GetSysModID() { return m_iSystem; }
// virtual const wchar_t* GetDesc();
public override string GetDesc()
{
return m_strDesc ?? string.Empty;
}
public override string GetIconFile()
{
return string.IsNullOrEmpty(m_IconFile) ? "unknown" : m_IconFile;
}
}
#endregion
}
@@ -9,13 +9,13 @@ namespace BrewMonster
#if UNITY_EDITOR
private void Update()
{
if (Input.GetKeyDown(KeyCode.S))
if (Input.GetKeyDown(KeyCode.S) )
OnSkillDragDrop();
}
#endif
public void OnSkillDragDrop()
{
var iSlot = 2;
var iSlot = 1;
var nCombo = 2;
CECShortcutSet pSCS = CECUIManager.Instance.GetInGameUIMan().GetSCSByDlg(1);
if (pSCS.GetShortcut(iSlot - 1) == null || !EC_Game.GetConfigs().GetGameSettings().bLockQuickBar)
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2832b8373ed049a89499155c2a507557
timeCreated: 1770188709
@@ -0,0 +1,39 @@
using BrewMonster.UI;
using UnityEngine;
using UnityEngine.UI;
namespace BrewMonster.Scripts
{
public class CDlgExit : AUIDialog
{
[SerializeField] private Button ConfirmBtn;
[SerializeField] private Button CancelBtn;
// [SerializeField] private Toggle CheckBox;
private void Awake()
{
ConfirmBtn.onClick.AddListener(OnCommand_confirm);
CancelBtn.onClick.AddListener(OnCancelClicked);
}
private void OnCancelClicked()
{
Show(false);
}
void OnCommand_confirm()
{
// TODO: Implement logout and exit logic
// if( m_pChk_Forcequit.isOn || !GetGameSession()->IsConnected())
// GetGameRun()->PostMessage(MSG_EXITGAME, -1, 0);
// else
// GetGameRun()->GetPendingLogOut().AppendForSaveConfig(new CECPendingLogoutFull());
CECGameRun.Instance.GetPendingLogOut().AppendForSaveConfig(new CECPendingLogoutFull());
Show(false);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8ca9d1418c284fd395248056f086c7d4
timeCreated: 1770188720
@@ -0,0 +1,33 @@
using System;
using BrewMonster.UI;
using UnityEngine;
using UnityEngine.UI;
namespace BrewMonster.Scripts
{
public class ExitTest : MonoBehaviour
{
private bool isExitDlgOpen = false;
private Button btn;
private void Start()
{
btn = GetComponent<Button>();
btn.onClick.AddListener(ToggleDlgExit);
}
private void Update()
{
if ( Input.GetKeyDown(KeyCode.Escape) )
{
ToggleDlgExit();
}
}
void ToggleDlgExit()
{
isExitDlgOpen = !isExitDlgOpen;
CECUIManager.Instance.GetInGameUIMan().GetDialog( "Win_Message2" ).Show( isExitDlgOpen );
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 96de7d56a4514c979bdd93568dba2031
timeCreated: 1770190994
@@ -160,6 +160,170 @@ namespace BrewMonster.UI
{
}
/// <summary>
/// Get user layout data for saving to server. Stub: returns size 0 (UI layout save not implemented).
/// 获取用户布局数据用于保存到服务器。桩:返回长度 0(UI 布局保存未实现)。
/// </summary>
/// TODO: NOW, IT ONLY RETURN THE FIXED SIZE OF STRUCTURE. NEED TO IMPLEMENT THE REAL DATA SAVE/LOAD.
public void GetUserLayout(byte[] pData, ref uint dwUISize)
{
if( pData != null )
{
// int i;
// USER_LAYOUT ul;
// char szName[40];
// PAUICHECKBOX pCheck;
// CECHostPlayer *pHost = g_pGame->GetGameRun()->GetHostPlayer();
//
// memset(&ul, 0, sizeof(USER_LAYOUT));
//
// ul.nVersion = LAYOUTDATA_VERSION;
// ul.nMapMode = m_pDlgMiniMap->GetMode();
//
// ul.bQuickbarPetMode = GetDialog("Win_QuickbarPetV")->IsShow();
//
// AString dlgName;
//
// dlgName.Format("Win_Quickbar%dHa", SIZE_HOSTSCSET1);
// ul.bQuickbar1Mode = GetDialog(dlgName)->IsShow();
// for( i = 0; i < NUM_HOSTSCSETS1; i++ )
// {
// sprintf(szName, "Win_Quickbar%dHb_%d", SIZE_HOSTSCSET1, i+1);
// pCheck = (PAUICHECKBOX)GetDialog(szName)->GetDlgItem("Chk_Normal");
// ul.bChecked1[i] = pCheck->IsChecked();
// }
//
// dlgName.Format("Win_Quickbar%dHa", SIZE_HOSTSCSET2);
// ul.bQuickbar2Mode = GetDialog(dlgName)->IsShow();
// for( i = 0; i < NUM_HOSTSCSETS2; i++ )
// {
// sprintf(szName, "Win_Quickbar%dHb_%d", SIZE_HOSTSCSET2, i+1);
// pCheck = (PAUICHECKBOX)GetDialog(szName)->GetDlgItem("Chk_Normal");
// ul.bChecked2[i] = pCheck->IsChecked();
// }
//
// m_pDlgTask->SyncTrace(&ul, false);
// ul.bQuickbarShowAll1 = CDlgQuickBar::m_bShowAll1;
// ul.bQuickbarShowAll2 = CDlgQuickBar::m_bShowAll2;
// ul.nQuickbarCurPanel1 = CDlgQuickBar::m_nCurPanel1;
// ul.nQuickbarCurPanel2 = CDlgQuickBar::m_nCurPanel2;
// ul.nQuickbarDisplayPanels1 = CDlgQuickBar::m_nDisplayPanels1;
// ul.nQuickbarDisplayPanels2 = CDlgQuickBar::m_nDisplayPanels2;
//
// ul.nChatWinSize = m_pDlgChat->GetChatWinSize();
// ul.nCurChatColor = m_pDlgChat->GetChatColor();
//
// for( i = 0; i < (int)m_pDlgMiniMap->GetMarks().size(); i++ )
// {
// ul.a_Mark[i].nNPC = m_pDlgMiniMap->GetMarks()[i].nNPC;
// ul.a_Mark[i].vecPos = m_pDlgMiniMap->GetMarks()[i].vecPos;
// ul.a_MarkMapID[i] = (short)m_pDlgMiniMap->GetMarks()[i].mapID;
// a_strncpy(ul.a_Mark[i].szName, m_pDlgMiniMap->GetMarks()[i].strName, CECGAMEUIMAN_MARK_NAME_LEN);
// }
//
// CECFriendMan::GROUP *pGroup;
// CECFriendMan *pMan = g_pGame->GetGameRun()->GetHostPlayer()->GetFriendMan();
// if (pMan)
// {
// int j(0);
// for( i = 0; i < pMan->GetGroupNum() && j < CECGAMEUIMAN_MAX_GROUPS; i++ )
// {
// pGroup = pMan->GetGroupByIndex(i);
// if (pGroup->iGroup)
// {
// ul.idGroup[j] = pGroup->iGroup;
// ul.clrGroup[j] = pGroup->color;
// ++ j;
// }
// }
// }
// ul.bAutoReply = m_bAutoReply;
// ul.bOnlineNotify = m_bOnlineNotify;
// ul.bSaveHistory = m_bSaveHistory;
//
// ul.ucCurSystemModuleSC = pHost->GetCurSysModShortcutSetIndex(); // ǰʹõϵͳģ
//
// ul.bSystemModuleQuickBarMini = m_pDlgSysModuleQuickBar->GetMiniMode();
//
// ul.bMenuMode = m_pDlgSystemb->IsShow();
//
// ul.bShowCompareDesc = m_bShowItemDescCompare;
// ul.bShowLowHP = m_bShowLowHP;
// ul.bShowTargetOfTarget = m_bShowTargetOfTarget;
//
// memcpy(pvData, &ul, sizeof(USER_LAYOUT));
//
// POINT ptPos;
// float fx, fy;
// AIniFile theIni;
// char szIniFile[MAX_PATH], szKey[40];
// A3DVIEWPORTPARAM *p = m_pA3DEngine->GetActiveViewport()->GetParam();
//
// for( i = 0; i < (int)m_aDialog.size() - 1; i++ )
// {
// ptPos = m_aDialog[i]->GetPos();
//
// fx = ptPos.x * 100.0f / p->Width;
// fy = ptPos.y * 100.0f / p->Height;
//
// //Խ԰UIλò
// /*
// if( dynamic_cast<CDlgHomeBase*>( m_aDialog[i]) != NULL)
// {
// continue;
// }
// */
//
// sprintf(szKey, "%s_x", m_aDialog[i]->GetName());
// theIni.WriteFloatValue("Windows", szKey, fx);
//
// sprintf(szKey, "%s_y", m_aDialog[i]->GetName());
// theIni.WriteFloatValue("Windows", szKey, fy);
// }
//
// // ͬ "Win_ELFZoom""Win_ELF" λ
// //
// PAUIDIALOG pDlg(NULL);
// if (GetDialog("Win_ELF")->IsShow())
// {
// pDlg = GetDialog("Win_ELFZoom");
// ptPos = GetDialog("Win_ELF")->GetPos();
// }
// else if (GetDialog("Win_ELFZoom")->IsShow())
// {
// pDlg = GetDialog("Win_ELF");
// ptPos = GetDialog("Win_ELFZoom")->GetPos();
// }
// if (pDlg)
// {
// fx = ptPos.x * 100.0f / p->Width;
// fy = ptPos.y * 100.0f / p->Height;
//
// sprintf(szKey, "%s_x", pDlg->GetName());
// theIni.WriteFloatValue("Windows", szKey, fx);
//
// sprintf(szKey, "%s_y", pDlg->GetName());
// theIni.WriteFloatValue("Windows", szKey, fy);
// }
//
// sprintf(szIniFile, "%s\\Userdata\\Layout", af_GetBaseDir());
// CreateDirectoryA(szIniFile, NULL);
//
// sprintf(szIniFile, "%s\\UserData\\Layout\\%d.ini",
// af_GetBaseDir(), pHost->GetCharacterID());
// theIni.Save(szIniFile);
// theIni.Close();
}
else
{
// TODO: NEW STRUCT USER_LAYOUT
// dwSize = sizeof(USER_LAYOUT);
dwUISize = 344;
}
}
public override void Init()
{
base.Init();
@@ -25,6 +25,9 @@ namespace BrewMonster
private void OnEscapeClicked()
{
// Open the exit dialog , not directly exit the game
// return;
if(EC_Game.GetGameRun()?.GetHostPlayer() != null)
{
EC_Game.GetGameRun()?.GetHostPlayer().OnClickBtnEscape();
@@ -10,6 +10,9 @@ namespace BrewMonster.UI
{
public void OnClick()
{
CECUIManager.Instance.ShowUI( "Win_Message2" );
return;
UnityGameSession.ReturnToSelectRole();
}
}
@@ -3,6 +3,7 @@ using System.IO;
using System.IO.Compression;
using Unity.SharpZipLib.Zip.Compression.Streams;
using UnityEngine;
using CompressionLevel = System.IO.Compression.CompressionLevel;
namespace BrewMonster
{
@@ -33,6 +34,75 @@ namespace BrewMonster
return result;
}
/// <summary>
/// Compress data in zlib format (2-byte header + deflate + 4-byte Adler-32), matching what UnCompress expects.
/// 压缩为 zlib 格式(2 字节头 + deflate + 4 字节 Adler-32),与 UnCompress 一致。
/// </summary>
/// <param name="dstOffset">Start index in dst where compressed bytes are written. 压缩数据写入 dst 的起始下标。</param>
/// <param name="dstLen">On input max length; on output actual compressed length. 输入为最大长度,输出为实际压缩长度。</param>
/// <returns>0 ok, non-zero error</returns>
public static int Compress(byte[] src, int srcOffset, int srcLen, byte[] dst, int dstOffset, ref int dstLen)
{
try
{
// Raw deflate into temporary buffer (same as decompression uses DeflateStream)
byte[] deflateBytes;
using (var deflateOutput = new MemoryStream())
{
using (var deflate = new DeflateStream(deflateOutput, CompressionLevel.Optimal))
{
deflate.Write(src, srcOffset, srcLen);
}
deflateBytes = deflateOutput.ToArray();
}
// Zlib format: 2-byte header + deflate + 4-byte Adler-32 (matches ZlibUnCompressDeflate which skips 2, length-6)
const int zlibHeaderLen = 2;
const int zlibFooterLen = 4;
int totalLen = zlibHeaderLen + deflateBytes.Length + zlibFooterLen;
if (dstOffset + totalLen > dst.Length)
return Z_BUF_ERROR;
int writeAt = dstOffset;
// 2-byte zlib header (deflate, 32K window, default compression)
dst[writeAt++] = 0x78;
dst[writeAt++] = 0x9C;
Buffer.BlockCopy(deflateBytes, 0, dst, writeAt, deflateBytes.Length);
writeAt += deflateBytes.Length;
// 4-byte Adler-32 of uncompressed data (big-endian)
uint adler = Adler32(src, srcOffset, srcLen);
dst[writeAt++] = (byte)(adler >> 24);
dst[writeAt++] = (byte)(adler >> 16);
dst[writeAt++] = (byte)(adler >> 8);
dst[writeAt++] = (byte)(adler);
dstLen = totalLen;
return Z_OK;
}
catch (Exception e)
{
Console.WriteLine($"ERROR::AFilePackage::Compress: {e.Message}");
return Z_ERROR;
}
}
private static uint Adler32(byte[] data, int offset, int length)
{
const uint Mod = 65521u;
uint a = 1u, b = 0u;
for (int i = 0; i < length; i++)
{
byte c = data[offset + i];
a = (a + c) % Mod;
b = (b + a) % Mod;
}
return (b << 16) | a;
}
private static int ZlibUnCompress(byte[] dest, ref int destLen, byte[] source, int sourceLen)
{
try
+179 -3
View File
@@ -20,6 +20,10 @@ public partial class CECGameRun
{
private static CECGameRun instance;
#region PROPERTIES AND FIELDS
private const uint USERCFG_VERSION = 3;
private GameObject _playerPrefab;
private GameObject _monsterPrefab;//CECMonster
private GameObject _npcServerPrefab;//CECNPCServer
@@ -41,6 +45,10 @@ public partial class CECGameRun
protected CECUIManager m_pUIManager; // UI manager
CECPendingActionArray m_pendingLogout;
#endregion
public CECWorld GetWorld()
{
@@ -66,6 +74,14 @@ public partial class CECGameRun
private int m_iDExpEndTime = 0;
// Cache for SaveConfigsToServer: last sent config data to skip duplicate sends
private byte[] m_pCfgDataBuf;
private int m_iCfgDataSize;
// Logout flag (C++: m_iLogoutFlag)
private int m_iLogoutFlag = -1;
// Selling role ID for role trade (C++: SetSellingRoleID/GetSellingRoleID)
private int m_iSellingRoleID;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void AfterSceneLoad()
@@ -102,6 +118,10 @@ public partial class CECGameRun
AddressableManager.Instance.OnDispose += Dispose;
m_pWorld = CECWorld.Instance;
StartGame(0, Vector3.zero);
m_pWorld = CECWorld.Instance;
m_pendingLogout = new CECPendingActionArray( false);
}
private static void Dispose()
@@ -310,8 +330,8 @@ public partial class CECGameRun
/// <returns>True if loaded successfully / 加载成功返回true</returns>
public bool LoadConfigsFromServer(byte[] pDataBuf, int iDataSize)
{
const uint USERCFG_VERSION = 3;
BMLogger.Log($"MH CECGameRun.LoadConfigsFromServer, iDataSize = {iDataSize}");
if (pDataBuf == null || iDataSize == 0)
{
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, configs data is empty");
@@ -747,10 +767,166 @@ public partial class CECGameRun
m_iDExpEndTime = endTime;
}
public int GetGameState() { return m_iGameState; }
public void SaveConfigsToServer()
// Logout flag: -1 none, 0 exit app, 1 re-select role, 2 goto login (C++: SetLogoutFlag/GetLogoutFlag)
public void SetLogoutFlag(int iFlag) { m_iLogoutFlag = iFlag; }
public int GetLogoutFlag() { return m_iLogoutFlag; }
// Selling role ID for role trade (C++: SetSellingRoleID)
public void SetSellingRoleID(int roleid) { m_iSellingRoleID = roleid; }
public int GetSellingRoleID() { return m_iSellingRoleID; }
// Save necessary user configs (UI, shortcut, accelerate keys, etc.) to server
// ֵ: 0(ʧ), 1(ظ), 2(Э)
public uint SaveConfigsToServer()
{
// if (!m_pWorld || !m_pWorld->GetHostPlayer() || !m_pWorld->GetHostPlayer()->HostIsReady() || !m_pUIManager->GetInGameUIMan())
// return 0;
CECHostPlayer pHost = GetHostPlayer();
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan() as CECGameUIMan;
if (m_pWorld == null || pHost == null || !pHost.HostIsReady() || pGameUI == null)
return 0;
// g_pGame->GetConfigs()->SaveBlockedID();
EC_Game.GetConfigs().SaveBlockedID(); // TODO: Check if this is needed here
// int iTotalSize = 0;
// iTotalSize += sizeof (DWORD);
// iTotalSize += sizeof (int);
// int iHostSize = 0;
// CECHostPlayer* pHost = m_pWorld->GetHostPlayer();
// pHost->SaveConfigData(NULL, &iHostSize);
// iTotalSize += iHostSize;
// iTotalSize += sizeof (int);
int iTotalSize = sizeof(uint);
iTotalSize += sizeof(int);
int iHostSize = 0;
pHost.SaveConfigData(null, ref iHostSize);
iTotalSize += sizeof(int) + iHostSize;
// DWORD dwUISize = 0;
// CECGameUIMan* pGameUI = (CECGameUIMan*)m_pUIManager->GetInGameUIMan();
// pGameUI->GetUserLayout(NULL, dwUISize);
// iTotalSize += (int)dwUISize;
// iTotalSize += sizeof (int);
uint dwUISize = 0;
pGameUI.GetUserLayout(null, ref dwUISize); // TODO: Check if this is needed here
iTotalSize += sizeof(int) + (int)dwUISize;
// int iSettingSize = 0;
// g_pGame->GetConfigs()->SaveUserConfigData(NULL, &iSettingSize);
// iTotalSize += iSettingSize;
int iSettingSize = 0;
EC_Game.GetConfigs().SaveUserConfigData(null, out iSettingSize);
// iTotalSize += sizeof(int) + iSettingSize;
iTotalSize += iSettingSize;
// void* pDataBuf = a_malloctemp(iTotalSize);
// if (!pDataBuf) { glb_ErrorOutput(ECERR_NOTENOUGHMEMORY, "CECGameRun::SaveConfigsToServer", __LINE__); return 0; }
// BYTE* pData = (BYTE*)pDataBuf;
byte[] pDataBuf = new byte[iTotalSize];
int offset = 0;
// *((DWORD*)pData) = USERCFG_VERSION;
// pData += sizeof (DWORD);
Buffer.BlockCopy(BitConverter.GetBytes(USERCFG_VERSION), 0, pDataBuf, offset, sizeof(uint));
offset += sizeof(uint);
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after version)");
// *((int*)pData) = iHostSize;
// pData += sizeof (int);
// pHost->SaveConfigData(pData, &iHostSize);
// pData += iHostSize;
Buffer.BlockCopy(BitConverter.GetBytes(iHostSize), 0, pDataBuf, offset, sizeof(int));
offset += sizeof(int);
pHost.SaveConfigData(pDataBuf, ref iHostSize, offset); // TODO: converted but need to check
offset += iHostSize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after host config, iHostSize={iHostSize})");
// *((int*)pData) = (int)dwUISize;
// pData += sizeof (int);
// pGameUI->GetUserLayout(pData, dwUISize);
// pData += dwUISize;
Buffer.BlockCopy(BitConverter.GetBytes((int)dwUISize), 0, pDataBuf, offset, sizeof(int));
offset += sizeof(int);
pGameUI.GetUserLayout(pDataBuf, ref dwUISize); // TODO: Check if this is needed here
offset += (int)dwUISize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after UI layout, dwUISize={dwUISize})");
// *((int*)pData) = iSettingSize;
// pData += sizeof (int);
// g_pGame->GetConfigs()->SaveUserConfigData(pData, &iSettingSize);
// pData += iSettingSize;
Buffer.BlockCopy(BitConverter.GetBytes(iSettingSize), 0, pDataBuf, offset, sizeof(int));
offset += sizeof(int);
EC_Game.GetConfigs().SaveUserConfigData(pDataBuf, offset, out iSettingSize);
offset += iSettingSize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after user config, iSettingSize={iSettingSize}), iTotalSize={iTotalSize}");
// if (m_pCfgDataBuf) {
// if (m_iCfgDataSize == iTotalSize && !memcmp(m_pCfgDataBuf, pDataBuf, iTotalSize)) { a_freetemp(pDataBuf); return 1; }
// a_free(m_pCfgDataBuf); m_pCfgDataBuf = NULL; m_iCfgDataSize = 0;
// }
if (m_pCfgDataBuf != null && m_iCfgDataSize == iTotalSize)
{
bool same = true;
for (int i = 0; i < iTotalSize && same; i++)
same = (m_pCfgDataBuf[i] == pDataBuf[i]);
if (same)
return 1;
}
m_pCfgDataBuf = null;
m_iCfgDataSize = 0;
// if ((m_pCfgDataBuf = (BYTE*)a_malloc(iTotalSize))) { memcpy(m_pCfgDataBuf, pDataBuf, iTotalSize); m_iCfgDataSize = iTotalSize; }
m_pCfgDataBuf = new byte[iTotalSize];
Buffer.BlockCopy(pDataBuf, 0, m_pCfgDataBuf, 0, iTotalSize);
m_iCfgDataSize = iTotalSize;
// DWORD dwCompLen = iTotalSize * 2;
// void* pCompBuf = a_malloctemp(dwCompLen);
// if (!pCompBuf) { a_freetemp(pDataBuf); glb_ErrorOutput(ECERR_NOTENOUGHMEMORY, "CECGameRun::SaveConfigsToServer", __LINE__); return 0; }
// int iVerLen = sizeof (DWORD);
// memcpy(pCompBuf, pDataBuf, iVerLen);
// BYTE* pSrc = (BYTE*)pDataBuf + iVerLen;
// BYTE* pDst = (BYTE*)pCompBuf + iVerLen;
// dwCompLen -= iVerLen;
// int iRes = AFilePackage::Compress(pSrc, iTotalSize - iVerLen, pDst, &dwCompLen);
int iVerLen = sizeof(uint);
// int compLen = (iTotalSize - iVerLen) * 2;
int compLen = iTotalSize * 2;
byte[] pCompBuf = new byte[iVerLen + compLen];
compLen -= iVerLen;
Buffer.BlockCopy(pDataBuf, 0, pCompBuf, 0, iVerLen);
int iRes = AFilePackage.Compress(pDataBuf, iVerLen,iTotalSize - iVerLen, pCompBuf, iVerLen, ref compLen);
// if (0 == iRes) { g_pGame->GetGameSession()->SaveConfigData(pCompBuf, dwCompLen+iVerLen); iRes = 2; }
// else { a_LogOutput(1, "CECGameRun::SaveConfigsToServer, Failed to compress config data (%d:%d)", iRes, iTotalSize); iRes = 0; }
// a_freetemp(pDataBuf);
// a_freetemp(pCompBuf);
// return iRes;
if (iRes == 0)
{
var session = UnityGameSession.Instance?.GameSession;
if (session != null)
{
session.SaveConfigData(pCompBuf, iVerLen + compLen);
return 2;
}
}
else
BMLogger.LogWarning($"CECGameRun::SaveConfigsToServer, Failed to compress config data ({iRes}:{iTotalSize})");
return 0;
}
public void ReleasePendingActions()
{
m_pendingLogout.Clear();
}
public CECPendingActionArray GetPendingLogOut(){ return m_pendingLogout; }
}
public enum GameState
+505
View File
@@ -0,0 +1,505 @@
using BrewMonster.Assets.PerfectWorld.Scripts.UI;
using BrewMonster.Scripts.Managers;
using CSNetwork.GPDataType;
using PerfectWorld.Scripts;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BrewMonster.Scripts;
namespace BrewMonster
{
public partial class CECHostPlayer
{
// Shortcut sets (converted from C++: m_aSCSets1[NUM_HOSTSCSETS1], m_aSCSets2[NUM_HOSTSCSETS2], m_aSCSetSysMod[NUM_SYSMODSETS])
public CECShortcutSet[] m_aSCSets1 = new CECShortcutSet[HostCfgConstants.NUM_HOSTSCSETS1]; // SC set 1
public CECShortcutSet[] m_aSCSets2 = new CECShortcutSet[HostCfgConstants.NUM_HOSTSCSETS2]; // SC set 2
public CECShortcutSet[]
m_aSCSetSysMod = new CECShortcutSet[HostCfgConstants.NUM_SYSMODSETS]; // System module shortcut sets
public int[]
m_aFashionSCSets = new int[HostCfgConstants.SIZE_FASHIONSCSET]; // Auto fashion shortcut sets (indices)
// C++: CECDealInventory* m_pBoothBPack / m_pBoothSPack booth buy pack and sell pack
private CECDealInventory m_pBoothBPack = null; // 摆摊收购包 Booth buy pack
private CECDealInventory m_pBoothSPack = null; // 摆摊出售包 Booth sell pack
BOOTH_AUTO_YINPIAO m_AutoYinpiao;
// C++: Host config constants (version, shortcut set counts/sizes)
private static class HostCfgConstants
{
public const int HOSTCFG_VERSION = 11;
public const int NUM_HOSTSCSETS1 = 5; // expanded from 3 to 5 (2009.05.27)
public const int NUM_HOSTSCSETS2 = 3;
public const int SIZE_HOSTSCSET1 = 9; // expanded from 6 to 9 (2009.05.27)
public const int SIZE_HOSTSCSET2 = 8;
public const int NUM_SYSMODSETS = 4; // System module shortcut sets count
public const int SIZE_SYSMODSCSET = 4; // System module shortcut set size (first 4 slots)
public const int SIZE_FASHIONSCSET = 240;
}
// Load configs data (shortcut, etc.) from specified buffer
// Converted from: bool CECHostPlayer::LoadConfigData(const void* pDataBuf)
public bool LoadConfigData(byte[] dataBuf)
{
if (dataBuf == null || dataBuf.Length < sizeof(uint))
return false;
int offset = 0;
// Version number
uint dwVer = GPDataTypeHelper.FromBytes<uint>(dataBuf, offset);
offset += sizeof(uint);
if (dwVer > HostCfgConstants.HOSTCFG_VERSION)
{
return false;
}
// Load shortcut configs...
int iHostSCSets1 = (dwVer <= 4) ? 3 : HostCfgConstants.NUM_HOSTSCSETS1;
for (int i = 0; i < iHostSCSets1; i++)
{
if (offset >= dataBuf.Length)
return false;
if (m_aSCSets1[i] == null)
{
m_aSCSets1[i] = new CECShortcutSet();
m_aSCSets1[i].Init(HostCfgConstants.SIZE_HOSTSCSET1);
}
if (!m_aSCSets1[i].LoadConfigData(dataBuf, dwVer, ref offset))
return false;
}
for (int i = 0; i < HostCfgConstants.NUM_HOSTSCSETS2; i++)
{
if (offset >= dataBuf.Length)
break; // No more data; tolerate truncated optional parts
if (m_aSCSets2[i] == null)
{
m_aSCSets2[i] = new CECShortcutSet();
m_aSCSets2[i].Init(HostCfgConstants.SIZE_HOSTSCSET2);
}
if (!m_aSCSets2[i].LoadConfigData(dataBuf, dwVer, ref offset))
return false;
}
// Load auto fashion shortcut sets
// Load auto fashion shortcut sets
// if(dwVer > 5)
if (dwVer > 5)
{
// int size = 0;
// if (dwVer == 6) size = 120; else size = HostCfgConstants.SIZE_FASHIONSCSET;
int size = (dwVer == 6) ? 120 : HostCfgConstants.SIZE_FASHIONSCSET;
// for (i=0; i < size; i++)
for (int i = 0; i < size; i++)
{
// if (dwVer <= 8 && (i % 6 == 5)) continue;
if (dwVer <= 8 && (i % 6 == 5)) continue;
// m_aFashionSCSets[i] = *((int*)pData); pData += sizeof(int);
if (offset + sizeof(int) > dataBuf.Length) return false;
m_aFashionSCSets[i] = GPDataTypeHelper.FromBytes<int>(dataBuf, offset);
offset += sizeof(int);
}
}
// Load system module shortcut sets
// Load system module shortcut sets
// if(dwVer > 10)
if (dwVer > 10)
{
// for (i=0; i < NUM_SYSMODSETS; i++)
for (int iSysMod = 0; iSysMod < HostCfgConstants.NUM_SYSMODSETS; iSysMod++)
{
// (C#: bounds check; C++ advances pData so no separate check)
if (offset >= dataBuf.Length)
return false;
// (C#: lazy init; C++ assumes array already allocated)
if (m_aSCSetSysMod[iSysMod] == null)
{
m_aSCSetSysMod[iSysMod] = new CECShortcutSet();
m_aSCSetSysMod[iSysMod].Init(HostCfgConstants.SIZE_SYSMODSCSET);
}
// int iSize;
// if (!m_aSCSetSysMod[i]->LoadConfigData(pData, &iSize, dwVer)) return false;
if (!m_aSCSetSysMod[iSysMod].LoadConfigData(dataBuf, dwVer, ref offset))
return false;
// if (i==0) // 如果第一个4个位置均为空,则初始化默认快捷键 | If the first 4 slots are all empty, init default shortcuts
if (iSysMod == 0)
{
// CECShortcutSet *pSCS = m_aSCSetSysMod[0];
CECShortcutSet pSCS = m_aSCSetSysMod[0];
// int ksc = 0;
// for (ksc = 0;ksc<pSCS->GetShortcutNum();ksc++) { if (pSCS->GetShortcut(ksc)) break; }
int ksc;
for (ksc = 0; ksc < pSCS.GetShortcutNum(); ksc++)
{
if (pSCS.GetShortcut(ksc) != null)
break;
}
// if (ksc == pSCS->GetShortcutNum())
if (ksc == pSCS.GetShortcutNum())
{
// int c = CECUIConfig::Instance().GetGameUI().nDefaultSystemModuleIndex.size();
// c = min(c,4);
var defaultList = CECUIConfig.Instance.GetGameUI().nDefaultSystemModuleIndex;
int c = (defaultList != null) ? defaultList.Count : 0;
c = Math.Min(c, 4);
// for (int i=0;i<c;i++) pSCS->CreateSystemModuleShortcut(i, CECUIConfig::Instance().GetGameUI().nDefaultSystemModuleIndex[i]);
for (int j = 0; j < c; j++)
pSCS.CreateSystemModuleShortcut(j, defaultList[j]);
}
}
// pData += iSize; (C#: offset updated by LoadConfigData ref)
}
}
// Load Saved Booth Buy and Sell Pack
// 加载保存的摆摊收购包与出售包
// if (dwVer > 7) { struct BoothItem { ... }; BoothItem temp; const int nPacks = 2; ...
if (dwVer > 7)
{
// BoothItem temp;
BoothItem temp;
// const int nPacks = 2;
const int nPacks = 2;
// CECDealInventory *pBoothPacks[nPacks] = {GetBoothBuyPack(), GetBoothSellPack()};
CECDealInventory[] pBoothPacks = new CECDealInventory[] { GetBoothBuyPack(), GetBoothSellPack() };
// DWORD nMaxBoothPacks[nPacks] = {IVTRSIZE_BOOTHBPACK_MAX, IVTRSIZE_BOOTHSPACK_MAX};
uint[] nMaxBoothPacks = new uint[] { InventoryConst.IVTRSIZE_BOOTHBPACK_MAX, InventoryConst.IVTRSIZE_BOOTHSPACK_MAX };
// for (int k=0 ; k < nPacks; ++k)
for (int k = 0; k < nPacks; ++k)
{
// CECDealInventory *pBoothPack = pBoothPacks[k];
CECDealInventory pBoothPack = pBoothPacks[k];
// bool isBuyPack = (pBoothPack == GetBoothBuyPack());
bool isBuyPack = (pBoothPack == GetBoothBuyPack());
// DWORD dwCurSize = pBoothPack->GetSize();
int dwCurSize = (pBoothPack != null) ? pBoothPack.GetSize() : 0;
// DWORD dwSize = *((DWORD *)pData); pData += sizeof(dwSize);
if (offset + sizeof(uint) > dataBuf.Length)
return false;
uint dwSize = GPDataTypeHelper.FromBytes<uint>(dataBuf, offset);
offset += sizeof(uint);
// ֤ݣг
// 验证数据,防止越界读取 | Verify data, prevent out-of-bounds read
if (dwSize > nMaxBoothPacks[k])
{
UnityEngine.Debug.LogWarningFormat("CECHostPlayer::LoadConfigData, Failed because pack {0} size invalid ({1}:{2}).", k, dwSize, nMaxBoothPacks[k]);
return false;
}
for (uint i = 0; i < dwSize; ++i)
{
// İСܿ뵱ǰСͬԵǰСΪ׼
// 保存的包大小可能和当前背包大小不同,以当前背包大小为准 | Saved pack size may differ from current; use current as reference
if (i < (uint)dwCurSize)
{
if (offset + Marshal.SizeOf<BoothItem>() > dataBuf.Length)
return false;
temp = GPDataTypeHelper.FromBytes<BoothItem>(dataBuf, offset);
// ֤ȡݵĺϷ
if (temp.idItem > 0 &&
temp.iAmount > 0 &&
temp.iUnitPrice >= 0 &&
temp.iOrigin >= 0)
{
EC_IvtrItem pItem2 = m_pPack.GetItem((int)temp.iOrigin, false);
if (pItem2 != null && pItem2.GetTemplateID() == (int)temp.idItem)
{
// ƷڵǰȷԭƷͬƷ
int iAmount = isBuyPack ? (int)temp.iAmount : EC_Utility.a_Min((int)temp.iAmount, pItem2.GetCount());
if (pBoothPack != null)
pBoothPack.AddBoothItem(pItem2, (int)temp.iOrigin, iAmount, (int)temp.iUnitPrice);
}
}
}
offset += Marshal.SizeOf<BoothItem>();
}
}
}
// Notes:
// - Auto fashion sets, system module shortcut sets, booth packs, and AutoYinpiao
// sections from native are not loaded here in this Unity port yet.
// The native format appends these after the two shortcut-set groups.
// We intentionally ignore them safely for now.
return true;
}
/// <summary>
/// Save host config (shortcut sets, etc.) to buffer. When pData is null, only outputs size in iHostSize.
/// 保存主机配置(快捷键组等)到缓冲区。pData 为 null 时仅输出 iHostSize。
/// </summary>
/// <param name="writeOffset">When pData is not null, write at this index. 写入时的起始下标。</param>
public bool SaveConfigData(byte[] pData, ref int iHostSize, int writeOffset = 0)
{
var list = new List<byte>();
list.AddRange(BitConverter.GetBytes(HostCfgConstants.HOSTCFG_VERSION));
for (int i = 0; i < m_aSCSets1.Length; i++)
{
if (m_aSCSets1[i] == null || !m_aSCSets1[i].SaveConfigData(out byte[] buf))
continue;
list.AddRange(buf);
}
for (int i = 0; i < m_aSCSets2.Length; i++)
{
if (m_aSCSets2[i] == null || !m_aSCSets2[i].SaveConfigData(out byte[] buf))
continue;
list.AddRange(buf);
}
// Save auto fashion shortcut sets | 保存自动时装快捷键组
// if(pDataBuf)
// {
// for (i=0; i < SIZE_FASHIONSCSET; i++)
// {
// *((int*)pData) = m_aFashionSCSets[i];
// if(pData)
// pData += sizeof (int);
// }
// }
// iTotalSize += sizeof(int) * SIZE_FASHIONSCSET;
for (int i = 0; i < HostCfgConstants.SIZE_FASHIONSCSET; i++)
{
list.AddRange(BitConverter.GetBytes(m_aFashionSCSets[i]));
}
// Save system module shortcut sets | 保存系统模块快捷键组
// for (i=0; i < NUM_SYSMODSETS; i++)
// {
// m_aSCSetSysMod[i]->SaveConfigData(pData, &iSize);
// iTotalSize += iSize;
// if (pData)
// pData += iSize;
// }
for (int i = 0; i < HostCfgConstants.NUM_SYSMODSETS; i++)
{
if (m_aSCSetSysMod[i] == null || !m_aSCSetSysMod[i].SaveConfigData(out byte[] buf))
continue;
list.AddRange(buf);
}
// Save Booth Buy and Sell Pack
// 保存摆摊收购包与出售包
// CECDealInventory *pBoothPacks[2] = {GetBoothBuyPack(), GetBoothSellPack()};
CECDealInventory[] pBoothPacks = new CECDealInventory[] { GetBoothBuyPack(), GetBoothSellPack() };
// for (int k=0 ; k < sizeof(pBoothPacks)/sizeof(pBoothPacks[0]); ++k)
for (int k = 0; k < pBoothPacks.Length; ++k)
{
// CECDealInventory *pBoothPack = pBoothPacks[k];
CECDealInventory pBoothPack = pBoothPacks[k];
// bool isBuyPack = (pBoothPack == GetBoothBuyPack());
bool isBuyPack = (pBoothPack == GetBoothBuyPack());
// DWORD dwSize = pBoothPack->GetSize();
uint dwSize = (uint)(pBoothPack != null ? pBoothPack.GetSize() : 0);
// if (pData) { *((DWORD *)pData) = dwSize; pData += sizeof(DWORD);
list.AddRange(BitConverter.GetBytes(dwSize));
//
// BoothItem temp; for (DWORD i = 0; i < dwSize; ++ i)
if (pBoothPack != null)
{
for (uint i = 0; i < dwSize; ++i)
{
// ::ZeroMemory(&temp, sizeof(temp));
BoothItem temp = default;
// const CECDealInventory::ITEMINFO &ii = pBoothPack->GetItemInfo(i);
CECDealInventory_ITEMINFO ii = pBoothPack.GetItemInfo((int)i);
// CECIvtrItem* pItem1 = pBoothPack->GetItem(i);
EC_IvtrItem pItem1 = pBoothPack.GetItem((int)i);
// if (pItem1) { CECIvtrItem* pItem2 = m_pPack->GetItem(ii.iOrigin);
if (pItem1 != null)
{
// CECIvtrItem* pItem2 = m_pPack->GetItem(ii.iOrigin);
EC_IvtrItem pItem2 = m_pPack.GetItem(ii.iOrigin, false);
// if (pItem2 && pItem2->GetTemplateID() == pItem1->GetTemplateID())
if (pItem2 != null && pItem2.GetTemplateID() == pItem1.GetTemplateID())
{
// temp.idItem = pItem1->GetTemplateID(); temp.iOrigin = ii.iOrigin;
temp.idItem = (uint)pItem1.GetTemplateID();
temp.iOrigin = (uint)ii.iOrigin;
// temp.iUnitPrice = pItem1->GetUnitPrice();
temp.iUnitPrice = (uint)pItem1.GetUnitPrice();
// temp.iAmount = isBuyPack ? ii.iAmount : a_Min(ii.iAmount, pItem2->GetCount());
temp.iAmount = isBuyPack
? (uint)ii.iAmount
: (uint)Math.Min(ii.iAmount, pItem2.GetCount());
}
}
//
// *((BoothItem *)pData) = temp; pData += sizeof(temp);
list.AddRange(BitConverter.GetBytes(temp.idItem));
list.AddRange(BitConverter.GetBytes(temp.iOrigin));
list.AddRange(BitConverter.GetBytes(temp.iAmount));
list.AddRange(BitConverter.GetBytes(temp.iUnitPrice));
}
}
// } iTotalSize += sizeof(DWORD) + dwSize * sizeof(BoothItem);
}
// ƱԶת
list.AddRange( BitConverter.GetBytes(m_AutoYinpiao.low_money) );
list.AddRange( BitConverter.GetBytes(m_AutoYinpiao.high_money) );
iHostSize = list.Count;
if (pData != null && writeOffset >= 0 && writeOffset + iHostSize <= pData.Length)
Buffer.BlockCopy(list.ToArray(), 0, pData, writeOffset, iHostSize);
return true;
}
// C++: GetBoothBuyPack() / GetBoothSellPack()
// 获取摆摊收购包 / 摆摊出售包
public CECDealInventory GetBoothBuyPack() => m_pBoothBPack;
public CECDealInventory GetBoothSellPack() => m_pBoothSPack;
bool CreateInventories()
{
// only use to init the booth inventories
if (m_pBoothBPack == null)
{
m_pBoothBPack = new CECDealInventory();
m_pBoothBPack.Init(InventoryConst.IVTRSIZE_BOOTHBPACK);
}
if (m_pBoothSPack == null)
{
m_pBoothSPack = new CECDealInventory();
m_pBoothSPack.Init(InventoryConst.IVTRSIZE_BOOTHSPACK);
}
return true;
}
}
// C++: struct BoothItem (save format for booth buy/sell pack item)
// 摆摊买卖包单项保存结构
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BoothItem
{
public uint idItem;
public uint iOrigin;
public uint iAmount;
public uint iUnitPrice;
}
// C++: CECDealInventory::ITEMINFO (EC_DealInventory.h)
// 物品附加信息
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CECDealInventory_ITEMINFO
{
public int iOrigin; // 原始位置 Original position in player's normal pack
public int iAmount; // 数量 Amount
[MarshalAs(UnmanagedType.Bool)]
public bool bDelete; // true 时物品对象可释放 true, item object can be released
public int iFlag; // 物品标志 Item flag
}
// C++: CECDealInventory (EC_DealInventory.h / EC_DealInventory.cpp) minimal view for SaveConfigData
// 交易/摆摊背包,仅提供保存配置所需的接口
public class CECDealInventory : EC_Inventory
{
// private readonly List<EC_IvtrItem> m_aItems = new List<EC_IvtrItem>();
private readonly List<CECDealInventory_ITEMINFO> m_aItemInfo = new List<CECDealInventory_ITEMINFO>();
// public int GetSize() => m_aItems.Count;
public CECDealInventory_ITEMINFO GetItemInfo(int n) => m_aItemInfo[n];
// public EC_IvtrItem GetItem(int i) => (i >= 0 && i < m_aItems.Count) ? m_aItems[i] : null;
// C++: AddBoothItem(pItem, iOrigin, iAmount, iUnitPrice) add item to booth pack with origin/amount/price
public void AddBoothItem(EC_IvtrItem pItem, int iOrigin, int iAmount, int iUnitPrice)
{
int slot = SearchEmpty();
if (slot < 0)
return;
while (m_aItemInfo.Count <= slot)
m_aItemInfo.Add(default);
m_aItemInfo[slot] = new CECDealInventory_ITEMINFO { iOrigin = iOrigin, iAmount = iAmount, bDelete = false, iFlag = 0 };
SetItem(slot, pItem);
if (pItem != null)
pItem.SetUnitPrice(iUnitPrice);
}
// Resize inventory
// C++: void CECDealInventory::Resize(int iNewSize)
public override void Resize(int iNewSize)
{
// int iOldSize = m_aItemInfo.GetSize();
int iOldSize = m_aItemInfo.Count;
// if(iNewSize < iOldSize) { for(int i=iNewSize;i<iOldSize;i++) { if (m_aItems[i] && m_aItemInfo[i].bDelete) delete m_aItems[i]; } }
if (iNewSize < iOldSize)
{
for (int i = iNewSize; i < iOldSize; i++)
{
if (GetItem(i) != null && m_aItemInfo[i].bDelete)
SetItem(i, null); // C#: release reference instead of delete
}
}
// CECInventory::Resize(iNewSize);
base.Resize(iNewSize);
// m_aItemInfo.SetSize(iNewSize, 10);
if (m_aItemInfo.Count > iNewSize)
m_aItemInfo.RemoveRange(iNewSize, m_aItemInfo.Count - iNewSize);
while (m_aItemInfo.Count < iNewSize)
m_aItemInfo.Add(default);
// if(iOldSize < iNewSize) { /* Clear new slots */ for (int i=iOldSize; i < iNewSize; i++) { m_aItemInfo[i].iOrigin = 0; ... } }
if (iOldSize < iNewSize)
{
// Clear new slots
for (int i = iOldSize; i < iNewSize; i++)
{
m_aItemInfo[i] = new CECDealInventory_ITEMINFO
{
iOrigin = 0,
iAmount = 0,
bDelete = false,
iFlag = 0
};
}
}
}
}
// ̯ƱԶת
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BOOTH_AUTO_YINPIAO
{
public bool open;
public CECCounter cnt;
public int low_money;
public int high_money;
// C++: BOOTH_AUTO_YINPIAO() : open(false), low_money(50000000), high_money(100000000) { cnt.SetPeriod(60000); cnt.Reset(true); }
public BOOTH_AUTO_YINPIAO(int i=0)
{
open = false;
low_money = 50000000;
high_money = 100000000;
cnt = new CECCounter();
cnt.SetPeriod(60000);
cnt.Reset(true);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2e2dc296cf794870802c33b2b2b8ff28
timeCreated: 1770696658
+4 -72
View File
@@ -51,10 +51,8 @@ namespace BrewMonster
private bool m_bJumpInWater = false;
public A3DVECTOR3 m_vVelocity; // Velocity
// Shortcut sets (converted from C++: m_aSCSets1[NUM_HOSTSCSETS1], m_aSCSets2[NUM_HOSTSCSETS2])
public CECShortcutSet[] m_aSCSets1 = new CECShortcutSet[HostCfgConstants.NUM_HOSTSCSETS1]; // SC set 1
public CECShortcutSet[] m_aSCSets2 = new CECShortcutSet[HostCfgConstants.NUM_HOSTSCSETS2]; // SC set 2
bool m_bChangingFace; // true, host is changing face
private int m_iRoleCreateTime;
private int m_iRoleLastLoginTime; // Role last login time
@@ -298,15 +296,6 @@ namespace BrewMonster
}
}
private static class HostCfgConstants
{
public const int HOSTCFG_VERSION = 11;
public const int NUM_HOSTSCSETS1 = 5; // expanded from 3 to 5 (2009.05.27)
public const int NUM_HOSTSCSETS2 = 3;
public const int SIZE_HOSTSCSET1 = 9; // expanded from 6 to 9 (2009.05.27)
public const int SIZE_HOSTSCSET2 = 8;
}
private void Awake()
{
base.Awake();
@@ -332,6 +321,8 @@ namespace BrewMonster
m_PetOptCnt.SetPeriod(1000);
m_PetOptCnt.Reset(true);
CreateInventories();
// run a process on background to keep track of task status.
UniTask.RunOnThreadPool(TickTask, false, this.GetCancellationTokenOnDestroy()).Forget();
}
@@ -1364,65 +1355,6 @@ namespace BrewMonster
return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
// Load configs data (shortcut, etc.) from specified buffer
// Converted from: bool CECHostPlayer::LoadConfigData(const void* pDataBuf)
public bool LoadConfigData(byte[] dataBuf)
{
if (dataBuf == null || dataBuf.Length < sizeof(uint))
return false;
int offset = 0;
// Version number
uint dwVer = GPDataTypeHelper.FromBytes<uint>(dataBuf, offset);
offset += sizeof(uint);
if (dwVer > HostCfgConstants.HOSTCFG_VERSION)
{
return false;
}
// Load shortcut configs...
int iHostSCSets1 = (dwVer <= 4) ? 3 : HostCfgConstants.NUM_HOSTSCSETS1;
for (int i = 0; i < iHostSCSets1; i++)
{
if (offset >= dataBuf.Length)
return false;
if (m_aSCSets1[i] == null)
{
m_aSCSets1[i] = new CECShortcutSet();
m_aSCSets1[i].Init(HostCfgConstants.SIZE_HOSTSCSET1);
}
if (!m_aSCSets1[i].LoadConfigData(dataBuf, dwVer, ref offset))
return false;
}
for (int i = 0; i < HostCfgConstants.NUM_HOSTSCSETS2; i++)
{
if (offset >= dataBuf.Length)
break; // No more data; tolerate truncated optional parts
if (m_aSCSets2[i] == null)
{
m_aSCSets2[i] = new CECShortcutSet();
m_aSCSets2[i].Init(HostCfgConstants.SIZE_HOSTSCSET2);
}
if (!m_aSCSets2[i].LoadConfigData(dataBuf, dwVer, ref offset))
return false;
}
// Notes:
// - Auto fashion sets, system module shortcut sets, booth packs, and AutoYinpiao
// sections from native are not loaded here in this Unity port yet.
// The native format appends these after the two shortcut-set groups.
// We intentionally ignore them safely for now.
return true;
}
public int GetCharacterID()
{
return m_PlayerInfo.cid;