구글 시트 연동 아키텍쳐 분리
This commit is contained in:
parent
2228efe47d
commit
b103ea6af0
BIN
Assets/AddressableAssetsData/AssetGroups/GoogleSheetSo_Group.asset
(Stored with Git LFS)
BIN
Assets/AddressableAssetsData/AssetGroups/GoogleSheetSo_Group.asset
(Stored with Git LFS)
Binary file not shown.
@ -9,7 +9,6 @@ GameObject:
|
|||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 4476251547817182662}
|
- component: {fileID: 4476251547817182662}
|
||||||
- component: {fileID: 6289760680591803305}
|
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: GoogleSheetManager
|
m_Name: GoogleSheetManager
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -32,34 +31,3 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!114 &6289760680591803305
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6237816563216546680}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 2631101f894592945a1c50aed7048e66, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
_persistent: 1
|
|
||||||
_isAccessGoogleSheet: 1
|
|
||||||
_googleSheetUrl: https://script.google.com/macros/s/AKfycbw8TRSl_OuY2S-RX0yvOJi1SqNqoflG0R3pWxk9GC9u_wvGQeuABZc0VH7YJ5lMrAl4/exec
|
|
||||||
_namespace: DDD
|
|
||||||
_autoCreateSheets:
|
|
||||||
- ItemData
|
|
||||||
- RecipeData
|
|
||||||
- FoodData
|
|
||||||
- DrinkData
|
|
||||||
- IngredientData
|
|
||||||
- CookwareData
|
|
||||||
- EnvironmentData
|
|
||||||
_soSyncSheets:
|
|
||||||
- TasteData
|
|
||||||
_generateFolderPath: /_DDD/_Scripts/GenerateGoogleSheet/AutoCreated
|
|
||||||
_currentVersion: "0 - 2025-08-08 19:40:27 by \uB0A8\uD0DC\uAC74"
|
|
||||||
_restoreIndex: 0
|
|
||||||
_editorName:
|
|
||||||
_refreshTrigger: 1
|
|
||||||
|
BIN
Assets/_DDD/_ScriptAssets/So/GoogleSheetManager.asset
(Stored with Git LFS)
Normal file
BIN
Assets/_DDD/_ScriptAssets/So/GoogleSheetManager.asset
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dd926e8709e44f347b04909219c78a6a
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
BIN
Assets/_DDD/_ScriptAssets/So/GoogleSheetSettingsSo.asset
(Stored with Git LFS)
Normal file
BIN
Assets/_DDD/_ScriptAssets/So/GoogleSheetSettingsSo.asset
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bafacdb9dade16f4790e4400e9ce5879
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
43
Assets/_DDD/_Scripts/GameData/TasteData.cs
Normal file
43
Assets/_DDD/_Scripts/GameData/TasteData.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// <auto-generated>
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public enum TasteType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Sweet = 1,
|
||||||
|
Warm = 2,
|
||||||
|
Vegetable = 3,
|
||||||
|
Bitter = 4,
|
||||||
|
Salty = 5,
|
||||||
|
Mild = 6,
|
||||||
|
Addictive = 7,
|
||||||
|
Sour = 8,
|
||||||
|
Savory = 9,
|
||||||
|
Meat = 10,
|
||||||
|
SuperHot = 11,
|
||||||
|
Fish = 12,
|
||||||
|
NoneDegree = 13,
|
||||||
|
Soda = 14,
|
||||||
|
LowDegree = 15,
|
||||||
|
WoodFlavor = 16,
|
||||||
|
MiddleDegree = 17,
|
||||||
|
FruitFlavor = 18,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class TasteData : IId
|
||||||
|
{
|
||||||
|
/// <summary>식별ID</summary>
|
||||||
|
[Tooltip("식별ID")]
|
||||||
|
[field: SerializeField]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>맛 종류</summary>
|
||||||
|
[Tooltip("맛 종류")]
|
||||||
|
public TasteType TasteType;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fa2ac723705c9624dadd61b238ad2819
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 52d686087dc8f2b45afa9f4e757e66a1
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: be71db161987564429bd0e62591815eb
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 582a711af5879c942b17b9936b8871e0
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -58,10 +58,419 @@
|
|||||||
"": "FruitFlavor"
|
"": "FruitFlavor"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"Test": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customers:string": "등장 손님",
|
||||||
|
"Test": 2352,
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": 0,
|
||||||
|
"Tests": "테스트, 테스트2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customers:string": "customer_001 | customer_002",
|
||||||
|
"Test": 3,
|
||||||
|
"Tests": "1 , 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customers:string": "customer_001 | customer_002 | customer_003",
|
||||||
|
"Test": 2,
|
||||||
|
"Tests": "5, 23,253"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": "435, 25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customers:string": "special_customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": "111|234"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Test_view": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customers1": "등장 손님1",
|
||||||
|
"Customers2": "등장 손님2",
|
||||||
|
"Customers3": "등장 손님3",
|
||||||
|
"Customers4": "등장 손님4",
|
||||||
|
"Customers5": "등장 손님5",
|
||||||
|
"Customers6": "등장 손님6",
|
||||||
|
"Test": 2352,
|
||||||
|
"Tests1": "Tests1",
|
||||||
|
"Tests2": "Tests2",
|
||||||
|
"Tests3": "Tests3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 0,
|
||||||
|
"Tests1": "테스트",
|
||||||
|
"Tests2": "테스트2",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "customer_002",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 3,
|
||||||
|
"Tests1": 1,
|
||||||
|
"Tests2": 2,
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "customer_002",
|
||||||
|
"Customers3": "customer_003",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 2,
|
||||||
|
"Tests1": 5,
|
||||||
|
"Tests2": 23,
|
||||||
|
"Tests3": 253
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": "",
|
||||||
|
"Tests2": "",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": 435,
|
||||||
|
"Tests2": 25,
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": "",
|
||||||
|
"Tests2": "",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customers1": "special_customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": 111,
|
||||||
|
"Tests2": 234,
|
||||||
|
"Tests3": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CustomerPoolData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customer1": "등장 손님1",
|
||||||
|
"Customer2": "등장 손님2",
|
||||||
|
"Customer3": "등장 손님3",
|
||||||
|
"Customer4": "등장 손님4",
|
||||||
|
"Customer5": "등장 손님5",
|
||||||
|
"Customer6": "등장 손님6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "customer_002",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "customer_002",
|
||||||
|
"Customer3": " customer_003",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customer1": "special_customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"LevelData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"Area": "등장 지역",
|
||||||
|
"CustomerPool": "일반 손님 풀",
|
||||||
|
"SpecialCustomerPool": "스페셜 손님 풀",
|
||||||
|
"FixSpecialCustomerCount": "확정 스페셜 손님 수",
|
||||||
|
"AddSpecialCustomerCount": "추가 스페셜 손님 확률",
|
||||||
|
"CustomerRespawnTime": "손님 리스폰 시간",
|
||||||
|
"Exp": "손님 1명당 경험치",
|
||||||
|
"OrderTime": "주문 대기 인내심 카운트 시간",
|
||||||
|
"WaitTime": "주문 인내심 카운트 시간",
|
||||||
|
"EatingTime": "식사 소요시간"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 1,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_001",
|
||||||
|
"SpecialCustomerPool": "",
|
||||||
|
"FixSpecialCustomerCount": 0,
|
||||||
|
"AddSpecialCustomerCount": 0,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 2,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_002",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 1,
|
||||||
|
"AddSpecialCustomerCount": 10,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 3,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_003",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 2,
|
||||||
|
"AddSpecialCustomerCount": 30,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 4,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_004",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 5,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_005",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 6,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_006",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CustomerData": [
|
||||||
|
{
|
||||||
|
"Id": "식별번호",
|
||||||
|
"CustomerType": "손님 타입",
|
||||||
|
"#Name": "이름",
|
||||||
|
"SpineSkinKey": "스파인 스킨 키 값",
|
||||||
|
"FavoriteTaste1": "선호 맛1",
|
||||||
|
"FavoriteTaste2": "선호 맛2",
|
||||||
|
"FavoriteTaste3": "선호 맛3",
|
||||||
|
"FavoriteTaste4": "선호 맛4",
|
||||||
|
"FavoriteTaste5": "선호 맛5",
|
||||||
|
"FavoriteTaste6": "선호 맛6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_001",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령1",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_002",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령2",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_003",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령3",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "special_customer_001",
|
||||||
|
"CustomerType": "Special",
|
||||||
|
"#Name": "차이",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
"ItemData": [
|
"ItemData": [
|
||||||
{
|
{
|
||||||
"Id": "식별번호",
|
"Id": "식별번호",
|
||||||
"ItemType:Enum": "아이템타입"
|
"ItemType:Enum": "아이템타입1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "item_food_001",
|
"Id": "item_food_001",
|
||||||
@ -1125,7 +1534,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "item_ingredient_005",
|
"Id:string": "item_ingredient_005",
|
||||||
"#Name": "치킨닭 고기"
|
"#Name": "미정"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "item_ingredient_006",
|
"Id:string": "item_ingredient_006",
|
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: d686bc895b261af419a5bdb06a243551
|
guid: e83477b2d57d3e247bf2b5ec240a731c
|
||||||
TextScriptImporter:
|
TextScriptImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
@ -58,10 +58,419 @@
|
|||||||
"": "FruitFlavor"
|
"": "FruitFlavor"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"Test": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customers:string": "등장 손님",
|
||||||
|
"Test": 2352,
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": 0,
|
||||||
|
"Tests": "테스트, 테스트2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customers:string": "customer_001 | customer_002",
|
||||||
|
"Test": 3,
|
||||||
|
"Tests": "1 , 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customers:string": "customer_001 | customer_002 | customer_003",
|
||||||
|
"Test": 2,
|
||||||
|
"Tests": "5, 23,253"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": "435, 25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customers:string": "special_customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": "111|234"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Test_view": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customers1": "등장 손님1",
|
||||||
|
"Customers2": "등장 손님2",
|
||||||
|
"Customers3": "등장 손님3",
|
||||||
|
"Customers4": "등장 손님4",
|
||||||
|
"Customers5": "등장 손님5",
|
||||||
|
"Customers6": "등장 손님6",
|
||||||
|
"Test": 2352,
|
||||||
|
"Tests1": "Tests1",
|
||||||
|
"Tests2": "Tests2",
|
||||||
|
"Tests3": "Tests3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 0,
|
||||||
|
"Tests1": "테스트",
|
||||||
|
"Tests2": "테스트2",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "customer_002",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 3,
|
||||||
|
"Tests1": 1,
|
||||||
|
"Tests2": 2,
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "customer_002",
|
||||||
|
"Customers3": "customer_003",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 2,
|
||||||
|
"Tests1": 5,
|
||||||
|
"Tests2": 23,
|
||||||
|
"Tests3": 253
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": "",
|
||||||
|
"Tests2": "",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": 435,
|
||||||
|
"Tests2": 25,
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": "",
|
||||||
|
"Tests2": "",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customers1": "special_customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": 111,
|
||||||
|
"Tests2": 234,
|
||||||
|
"Tests3": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CustomerPoolData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customer1": "등장 손님1",
|
||||||
|
"Customer2": "등장 손님2",
|
||||||
|
"Customer3": "등장 손님3",
|
||||||
|
"Customer4": "등장 손님4",
|
||||||
|
"Customer5": "등장 손님5",
|
||||||
|
"Customer6": "등장 손님6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "customer_002",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "customer_002",
|
||||||
|
"Customer3": " customer_003",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customer1": "special_customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"LevelData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"Area": "등장 지역",
|
||||||
|
"CustomerPool": "일반 손님 풀",
|
||||||
|
"SpecialCustomerPool": "스페셜 손님 풀",
|
||||||
|
"FixSpecialCustomerCount": "확정 스페셜 손님 수",
|
||||||
|
"AddSpecialCustomerCount": "추가 스페셜 손님 확률",
|
||||||
|
"CustomerRespawnTime": "손님 리스폰 시간",
|
||||||
|
"Exp": "손님 1명당 경험치",
|
||||||
|
"OrderTime": "주문 대기 인내심 카운트 시간",
|
||||||
|
"WaitTime": "주문 인내심 카운트 시간",
|
||||||
|
"EatingTime": "식사 소요시간"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 1,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_001",
|
||||||
|
"SpecialCustomerPool": "",
|
||||||
|
"FixSpecialCustomerCount": 0,
|
||||||
|
"AddSpecialCustomerCount": 0,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 2,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_002",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 1,
|
||||||
|
"AddSpecialCustomerCount": 10,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 3,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_003",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 2,
|
||||||
|
"AddSpecialCustomerCount": 30,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 4,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_004",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 5,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_005",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 6,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_006",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CustomerData": [
|
||||||
|
{
|
||||||
|
"Id": "식별번호",
|
||||||
|
"CustomerType": "손님 타입",
|
||||||
|
"#Name": "이름",
|
||||||
|
"SpineSkinKey": "스파인 스킨 키 값",
|
||||||
|
"FavoriteTaste1": "선호 맛1",
|
||||||
|
"FavoriteTaste2": "선호 맛2",
|
||||||
|
"FavoriteTaste3": "선호 맛3",
|
||||||
|
"FavoriteTaste4": "선호 맛4",
|
||||||
|
"FavoriteTaste5": "선호 맛5",
|
||||||
|
"FavoriteTaste6": "선호 맛6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_001",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령1",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_002",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령2",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_003",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령3",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "special_customer_001",
|
||||||
|
"CustomerType": "Special",
|
||||||
|
"#Name": "차이",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
"ItemData": [
|
"ItemData": [
|
||||||
{
|
{
|
||||||
"Id": "식별번호",
|
"Id": "식별번호",
|
||||||
"ItemType:Enum": "아이템타입"
|
"ItemType:Enum": "아이템타입1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "item_food_001",
|
"Id": "item_food_001",
|
||||||
@ -279,6 +688,14 @@
|
|||||||
"Id": "item_environment_cookware_006",
|
"Id": "item_environment_cookware_006",
|
||||||
"ItemType:Enum": "Environment"
|
"ItemType:Enum": "Environment"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_007",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_008",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Id": "item_drink_001",
|
"Id": "item_drink_001",
|
||||||
"ItemType:Enum": "Drink"
|
"ItemType:Enum": "Drink"
|
||||||
@ -548,7 +965,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "식별ID",
|
"Id:string": "식별ID",
|
||||||
"#Name": "이름",
|
"#Name": "이름",
|
||||||
"CookwareKey:string": "요리도구 타입",
|
"CookwareKey:string": "요리도구 키 값",
|
||||||
"CookTime:int": "요리시간",
|
"CookTime:int": "요리시간",
|
||||||
"Price:int": "요리가격",
|
"Price:int": "요리가격",
|
||||||
"IngredientKey1:string": "재료1",
|
"IngredientKey1:string": "재료1",
|
||||||
@ -991,7 +1408,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "식별ID",
|
"Id:string": "식별ID",
|
||||||
"#Name": "이름",
|
"#Name": "이름",
|
||||||
"CookwareType:Enum": "요리도구",
|
"CookwareKey:string": "요리도구 키 값",
|
||||||
"CookTime:int": "요리시간",
|
"CookTime:int": "요리시간",
|
||||||
"Price:int": "요리가격",
|
"Price:int": "요리가격",
|
||||||
"IngredientKey1:string": "재료1",
|
"IngredientKey1:string": "재료1",
|
||||||
@ -1012,7 +1429,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_drink_001",
|
"Id:string": "item_drink_001",
|
||||||
"#Name": "토마토 주스",
|
"#Name": "토마토 주스",
|
||||||
"CookwareType:Enum": "JuiceMachine",
|
"CookwareKey:string": "item_environment_cookware_007",
|
||||||
"CookTime:int": 1,
|
"CookTime:int": 1,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_006",
|
"IngredientKey1:string": "item_ingredient_006",
|
||||||
@ -1033,7 +1450,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_drink_002",
|
"Id:string": "item_drink_002",
|
||||||
"#Name": "오렌지 주스",
|
"#Name": "오렌지 주스",
|
||||||
"CookwareType:Enum": "JuiceMachine",
|
"CookwareKey:string": "item_environment_cookware_007",
|
||||||
"CookTime:int": 1,
|
"CookTime:int": 1,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_023",
|
"IngredientKey1:string": "item_ingredient_023",
|
||||||
@ -1054,7 +1471,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_drink_003",
|
"Id:string": "item_drink_003",
|
||||||
"#Name": "여신의눈물",
|
"#Name": "여신의눈물",
|
||||||
"CookwareType:Enum": "Barrel",
|
"CookwareKey:string": "item_environment_cookware_008",
|
||||||
"CookTime:int": 3,
|
"CookTime:int": 3,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_008",
|
"IngredientKey1:string": "item_ingredient_008",
|
||||||
@ -1075,7 +1492,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_drink_004",
|
"Id:string": "item_drink_004",
|
||||||
"#Name": "라벨블루",
|
"#Name": "라벨블루",
|
||||||
"CookwareType:Enum": "Barrel",
|
"CookwareKey:string": "item_environment_cookware_008",
|
||||||
"CookTime:int": 3,
|
"CookTime:int": 3,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_002",
|
"IngredientKey1:string": "item_ingredient_002",
|
||||||
@ -1117,7 +1534,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "item_ingredient_005",
|
"Id:string": "item_ingredient_005",
|
||||||
"#Name": "치킨닭 고기"
|
"#Name": "미정"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "item_ingredient_006",
|
"Id:string": "item_ingredient_006",
|
||||||
@ -1227,6 +1644,16 @@
|
|||||||
"Id:string": "item_environment_cookware_006",
|
"Id:string": "item_environment_cookware_006",
|
||||||
"#Name": "",
|
"#Name": "",
|
||||||
"CookwareType:Enum": "MagicOven"
|
"CookwareType:Enum": "MagicOven"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_007",
|
||||||
|
"#Name": "",
|
||||||
|
"CookwareType:Enum": "JuiceMachine"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_008",
|
||||||
|
"#Name": "",
|
||||||
|
"CookwareType:Enum": "Barrel"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"TasteData": [
|
"TasteData": [
|
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 56d87f6c872900b41beecc99b88b67af
|
guid: 0a7e264dbeab2004d972d028db1ed457
|
||||||
TextScriptImporter:
|
TextScriptImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
@ -58,10 +58,419 @@
|
|||||||
"": "FruitFlavor"
|
"": "FruitFlavor"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"Test": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customers:string": "등장 손님",
|
||||||
|
"Test": 2352,
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": 0,
|
||||||
|
"Tests": "테스트, 테스트2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customers:string": "customer_001 | customer_002",
|
||||||
|
"Test": 3,
|
||||||
|
"Tests": "1 , 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customers:string": "customer_001 | customer_002 | customer_003",
|
||||||
|
"Test": 2,
|
||||||
|
"Tests": "5, 23,253"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": "435, 25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customers:string": "special_customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": "111|234"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Test_view": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customers1": "등장 손님1",
|
||||||
|
"Customers2": "등장 손님2",
|
||||||
|
"Customers3": "등장 손님3",
|
||||||
|
"Customers4": "등장 손님4",
|
||||||
|
"Customers5": "등장 손님5",
|
||||||
|
"Customers6": "등장 손님6",
|
||||||
|
"Test": 2352,
|
||||||
|
"Tests1": "Tests1",
|
||||||
|
"Tests2": "Tests2",
|
||||||
|
"Tests3": "Tests3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 0,
|
||||||
|
"Tests1": "테스트",
|
||||||
|
"Tests2": "테스트2",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "customer_002",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 3,
|
||||||
|
"Tests1": 1,
|
||||||
|
"Tests2": 2,
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "customer_002",
|
||||||
|
"Customers3": "customer_003",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 2,
|
||||||
|
"Tests1": 5,
|
||||||
|
"Tests2": 23,
|
||||||
|
"Tests3": 253
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": "",
|
||||||
|
"Tests2": "",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": 435,
|
||||||
|
"Tests2": 25,
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": "",
|
||||||
|
"Tests2": "",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customers1": "special_customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": 111,
|
||||||
|
"Tests2": 234,
|
||||||
|
"Tests3": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CustomerPoolData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customer1": "등장 손님1",
|
||||||
|
"Customer2": "등장 손님2",
|
||||||
|
"Customer3": "등장 손님3",
|
||||||
|
"Customer4": "등장 손님4",
|
||||||
|
"Customer5": "등장 손님5",
|
||||||
|
"Customer6": "등장 손님6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "customer_002",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "customer_002",
|
||||||
|
"Customer3": " customer_003",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customer1": "special_customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"LevelData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"Area": "등장 지역",
|
||||||
|
"CustomerPool": "일반 손님 풀",
|
||||||
|
"SpecialCustomerPool": "스페셜 손님 풀",
|
||||||
|
"FixSpecialCustomerCount": "확정 스페셜 손님 수",
|
||||||
|
"AddSpecialCustomerCount": "추가 스페셜 손님 확률",
|
||||||
|
"CustomerRespawnTime": "손님 리스폰 시간",
|
||||||
|
"Exp": "손님 1명당 경험치",
|
||||||
|
"OrderTime": "주문 대기 인내심 카운트 시간",
|
||||||
|
"WaitTime": "주문 인내심 카운트 시간",
|
||||||
|
"EatingTime": "식사 소요시간"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 1,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_001",
|
||||||
|
"SpecialCustomerPool": "",
|
||||||
|
"FixSpecialCustomerCount": 0,
|
||||||
|
"AddSpecialCustomerCount": 0,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 2,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_002",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 1,
|
||||||
|
"AddSpecialCustomerCount": 10,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 3,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_003",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 2,
|
||||||
|
"AddSpecialCustomerCount": 30,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 4,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_004",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 5,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_005",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 6,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_006",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CustomerData": [
|
||||||
|
{
|
||||||
|
"Id": "식별번호",
|
||||||
|
"CustomerType": "손님 타입",
|
||||||
|
"#Name": "이름",
|
||||||
|
"SpineSkinKey": "스파인 스킨 키 값",
|
||||||
|
"FavoriteTaste1": "선호 맛1",
|
||||||
|
"FavoriteTaste2": "선호 맛2",
|
||||||
|
"FavoriteTaste3": "선호 맛3",
|
||||||
|
"FavoriteTaste4": "선호 맛4",
|
||||||
|
"FavoriteTaste5": "선호 맛5",
|
||||||
|
"FavoriteTaste6": "선호 맛6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_001",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령1",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_002",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령2",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_003",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령3",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "special_customer_001",
|
||||||
|
"CustomerType": "Special",
|
||||||
|
"#Name": "차이",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
"ItemData": [
|
"ItemData": [
|
||||||
{
|
{
|
||||||
"Id": "식별번호",
|
"Id": "식별번호",
|
||||||
"ItemType:Enum": "아이템타입"
|
"ItemType:Enum": "아이템타입1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "item_food_001",
|
"Id": "item_food_001",
|
||||||
@ -255,6 +664,38 @@
|
|||||||
"Id": "item_environment_005",
|
"Id": "item_environment_005",
|
||||||
"ItemType:Enum": "Environment"
|
"ItemType:Enum": "Environment"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_001",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_002",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_003",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_004",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_005",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_006",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_007",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "item_environment_cookware_008",
|
||||||
|
"ItemType:Enum": "Environment"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Id": "item_drink_001",
|
"Id": "item_drink_001",
|
||||||
"ItemType:Enum": "Drink"
|
"ItemType:Enum": "Drink"
|
||||||
@ -524,7 +965,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "식별ID",
|
"Id:string": "식별ID",
|
||||||
"#Name": "이름",
|
"#Name": "이름",
|
||||||
"CookwareType:Enum": "요리도구 타입",
|
"CookwareKey:string": "요리도구 키 값",
|
||||||
"CookTime:int": "요리시간",
|
"CookTime:int": "요리시간",
|
||||||
"Price:int": "요리가격",
|
"Price:int": "요리가격",
|
||||||
"IngredientKey1:string": "재료1",
|
"IngredientKey1:string": "재료1",
|
||||||
@ -545,7 +986,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_001",
|
"Id:string": "item_food_001",
|
||||||
"#Name": "블루 스튜",
|
"#Name": "블루 스튜",
|
||||||
"CookwareType:Enum": "Pot",
|
"CookwareKey:string": "item_environment_cookware_001",
|
||||||
"CookTime:int": 7,
|
"CookTime:int": 7,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_001",
|
"IngredientKey1:string": "item_ingredient_001",
|
||||||
@ -566,7 +1007,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_002",
|
"Id:string": "item_food_002",
|
||||||
"#Name": "햇빛 스튜",
|
"#Name": "햇빛 스튜",
|
||||||
"CookwareType:Enum": "Pot",
|
"CookwareKey:string": "item_environment_cookware_001",
|
||||||
"CookTime:int": 7,
|
"CookTime:int": 7,
|
||||||
"Price:int": 20,
|
"Price:int": 20,
|
||||||
"IngredientKey1:string": "item_ingredient_002",
|
"IngredientKey1:string": "item_ingredient_002",
|
||||||
@ -587,7 +1028,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_003",
|
"Id:string": "item_food_003",
|
||||||
"#Name": "심해기억 스튜",
|
"#Name": "심해기억 스튜",
|
||||||
"CookwareType:Enum": "Pot",
|
"CookwareKey:string": "item_environment_cookware_001",
|
||||||
"CookTime:int": 7,
|
"CookTime:int": 7,
|
||||||
"Price:int": 15,
|
"Price:int": 15,
|
||||||
"IngredientKey1:string": "item_ingredient_002",
|
"IngredientKey1:string": "item_ingredient_002",
|
||||||
@ -608,7 +1049,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_004",
|
"Id:string": "item_food_004",
|
||||||
"#Name": "치킨 굴라쉬",
|
"#Name": "치킨 굴라쉬",
|
||||||
"CookwareType:Enum": "Pot",
|
"CookwareKey:string": "item_environment_cookware_001",
|
||||||
"CookTime:int": 10,
|
"CookTime:int": 10,
|
||||||
"Price:int": 30,
|
"Price:int": 30,
|
||||||
"IngredientKey1:string": "item_ingredient_005",
|
"IngredientKey1:string": "item_ingredient_005",
|
||||||
@ -629,7 +1070,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_005",
|
"Id:string": "item_food_005",
|
||||||
"#Name": "꿈해초 크로켓",
|
"#Name": "꿈해초 크로켓",
|
||||||
"CookwareType:Enum": "Fryer",
|
"CookwareKey:string": "item_environment_cookware_002",
|
||||||
"CookTime:int": 5,
|
"CookTime:int": 5,
|
||||||
"Price:int": 20,
|
"Price:int": 20,
|
||||||
"IngredientKey1:string": "item_ingredient_007",
|
"IngredientKey1:string": "item_ingredient_007",
|
||||||
@ -650,7 +1091,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_006",
|
"Id:string": "item_food_006",
|
||||||
"#Name": "선라이즈 당근카츠",
|
"#Name": "선라이즈 당근카츠",
|
||||||
"CookwareType:Enum": "Fryer",
|
"CookwareKey:string": "item_environment_cookware_002",
|
||||||
"CookTime:int": 5,
|
"CookTime:int": 5,
|
||||||
"Price:int": 30,
|
"Price:int": 30,
|
||||||
"IngredientKey1:string": "item_ingredient_003",
|
"IngredientKey1:string": "item_ingredient_003",
|
||||||
@ -671,7 +1112,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_007",
|
"Id:string": "item_food_007",
|
||||||
"#Name": "미정",
|
"#Name": "미정",
|
||||||
"CookwareType:Enum": "Fryer",
|
"CookwareKey:string": "item_environment_cookware_002",
|
||||||
"CookTime:int": 5,
|
"CookTime:int": 5,
|
||||||
"Price:int": 30,
|
"Price:int": 30,
|
||||||
"IngredientKey1:string": "item_ingredient_011",
|
"IngredientKey1:string": "item_ingredient_011",
|
||||||
@ -692,7 +1133,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_008",
|
"Id:string": "item_food_008",
|
||||||
"#Name": "비늘치킨덕",
|
"#Name": "비늘치킨덕",
|
||||||
"CookwareType:Enum": "FirePit",
|
"CookwareKey:string": "item_environment_cookware_003",
|
||||||
"CookTime:int": 6,
|
"CookTime:int": 6,
|
||||||
"Price:int": 30,
|
"Price:int": 30,
|
||||||
"IngredientKey1:string": "item_ingredient_012",
|
"IngredientKey1:string": "item_ingredient_012",
|
||||||
@ -713,7 +1154,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_009",
|
"Id:string": "item_food_009",
|
||||||
"#Name": "화룡장어 구이",
|
"#Name": "화룡장어 구이",
|
||||||
"CookwareType:Enum": "FirePit",
|
"CookwareKey:string": "item_environment_cookware_003",
|
||||||
"CookTime:int": 6,
|
"CookTime:int": 6,
|
||||||
"Price:int": 15,
|
"Price:int": 15,
|
||||||
"IngredientKey1:string": "item_ingredient_014",
|
"IngredientKey1:string": "item_ingredient_014",
|
||||||
@ -734,7 +1175,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_010",
|
"Id:string": "item_food_010",
|
||||||
"#Name": "미정",
|
"#Name": "미정",
|
||||||
"CookwareType:Enum": "FirePit",
|
"CookwareKey:string": "item_environment_cookware_003",
|
||||||
"CookTime:int": 6,
|
"CookTime:int": 6,
|
||||||
"Price:int": 30,
|
"Price:int": 30,
|
||||||
"IngredientKey1:string": "item_ingredient_016",
|
"IngredientKey1:string": "item_ingredient_016",
|
||||||
@ -755,7 +1196,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_011",
|
"Id:string": "item_food_011",
|
||||||
"#Name": "바다의선물",
|
"#Name": "바다의선물",
|
||||||
"CookwareType:Enum": "CuttingBoard",
|
"CookwareKey:string": "item_environment_cookware_004",
|
||||||
"CookTime:int": 5,
|
"CookTime:int": 5,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_002",
|
"IngredientKey1:string": "item_ingredient_002",
|
||||||
@ -776,7 +1217,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_012",
|
"Id:string": "item_food_012",
|
||||||
"#Name": "유령새우회",
|
"#Name": "유령새우회",
|
||||||
"CookwareType:Enum": "CuttingBoard",
|
"CookwareKey:string": "item_environment_cookware_004",
|
||||||
"CookTime:int": 5,
|
"CookTime:int": 5,
|
||||||
"Price:int": 25,
|
"Price:int": 25,
|
||||||
"IngredientKey1:string": "item_ingredient_017",
|
"IngredientKey1:string": "item_ingredient_017",
|
||||||
@ -797,7 +1238,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_013",
|
"Id:string": "item_food_013",
|
||||||
"#Name": "비늘초무침",
|
"#Name": "비늘초무침",
|
||||||
"CookwareType:Enum": "CuttingBoard",
|
"CookwareKey:string": "item_environment_cookware_004",
|
||||||
"CookTime:int": 5,
|
"CookTime:int": 5,
|
||||||
"Price:int": 45,
|
"Price:int": 45,
|
||||||
"IngredientKey1:string": "item_ingredient_018",
|
"IngredientKey1:string": "item_ingredient_018",
|
||||||
@ -818,7 +1259,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_014",
|
"Id:string": "item_food_014",
|
||||||
"#Name": "쫀징어 냉채",
|
"#Name": "쫀징어 냉채",
|
||||||
"CookwareType:Enum": "CuttingBoard",
|
"CookwareKey:string": "item_environment_cookware_004",
|
||||||
"CookTime:int": 5,
|
"CookTime:int": 5,
|
||||||
"Price:int": 15,
|
"Price:int": 15,
|
||||||
"IngredientKey1:string": "item_ingredient_011",
|
"IngredientKey1:string": "item_ingredient_011",
|
||||||
@ -839,7 +1280,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_015",
|
"Id:string": "item_food_015",
|
||||||
"#Name": "쫀징어링",
|
"#Name": "쫀징어링",
|
||||||
"CookwareType:Enum": "Griddle",
|
"CookwareKey:string": "item_environment_cookware_005",
|
||||||
"CookTime:int": 8,
|
"CookTime:int": 8,
|
||||||
"Price:int": 25,
|
"Price:int": 25,
|
||||||
"IngredientKey1:string": "item_ingredient_011",
|
"IngredientKey1:string": "item_ingredient_011",
|
||||||
@ -860,7 +1301,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_016",
|
"Id:string": "item_food_016",
|
||||||
"#Name": "꿈해파리 볶음",
|
"#Name": "꿈해파리 볶음",
|
||||||
"CookwareType:Enum": "Griddle",
|
"CookwareKey:string": "item_environment_cookware_005",
|
||||||
"CookTime:int": 6,
|
"CookTime:int": 6,
|
||||||
"Price:int": 15,
|
"Price:int": 15,
|
||||||
"IngredientKey1:string": "item_ingredient_019",
|
"IngredientKey1:string": "item_ingredient_019",
|
||||||
@ -881,7 +1322,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_017",
|
"Id:string": "item_food_017",
|
||||||
"#Name": "페퍼포칼립스",
|
"#Name": "페퍼포칼립스",
|
||||||
"CookwareType:Enum": "Griddle",
|
"CookwareKey:string": "item_environment_cookware_005",
|
||||||
"CookTime:int": 6,
|
"CookTime:int": 6,
|
||||||
"Price:int": 25,
|
"Price:int": 25,
|
||||||
"IngredientKey1:string": "item_ingredient_012",
|
"IngredientKey1:string": "item_ingredient_012",
|
||||||
@ -902,7 +1343,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_018",
|
"Id:string": "item_food_018",
|
||||||
"#Name": "미정",
|
"#Name": "미정",
|
||||||
"CookwareType:Enum": "MagicOven",
|
"CookwareKey:string": "item_environment_cookware_006",
|
||||||
"CookTime:int": 0,
|
"CookTime:int": 0,
|
||||||
"Price:int": 0,
|
"Price:int": 0,
|
||||||
"IngredientKey1:string": "",
|
"IngredientKey1:string": "",
|
||||||
@ -923,7 +1364,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_019",
|
"Id:string": "item_food_019",
|
||||||
"#Name": "미정",
|
"#Name": "미정",
|
||||||
"CookwareType:Enum": "MagicOven",
|
"CookwareKey:string": "item_environment_cookware_006",
|
||||||
"CookTime:int": 0,
|
"CookTime:int": 0,
|
||||||
"Price:int": 0,
|
"Price:int": 0,
|
||||||
"IngredientKey1:string": "",
|
"IngredientKey1:string": "",
|
||||||
@ -944,7 +1385,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_food_020",
|
"Id:string": "item_food_020",
|
||||||
"#Name": "미정",
|
"#Name": "미정",
|
||||||
"CookwareType:Enum": "MagicOven",
|
"CookwareKey:string": "item_environment_cookware_006",
|
||||||
"CookTime:int": 0,
|
"CookTime:int": 0,
|
||||||
"Price:int": 0,
|
"Price:int": 0,
|
||||||
"IngredientKey1:string": "",
|
"IngredientKey1:string": "",
|
||||||
@ -967,7 +1408,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "식별ID",
|
"Id:string": "식별ID",
|
||||||
"#Name": "이름",
|
"#Name": "이름",
|
||||||
"CookwareType:Enum": "요리도구",
|
"CookwareKey:string": "요리도구 키 값",
|
||||||
"CookTime:int": "요리시간",
|
"CookTime:int": "요리시간",
|
||||||
"Price:int": "요리가격",
|
"Price:int": "요리가격",
|
||||||
"IngredientKey1:string": "재료1",
|
"IngredientKey1:string": "재료1",
|
||||||
@ -988,7 +1429,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_drink_001",
|
"Id:string": "item_drink_001",
|
||||||
"#Name": "토마토 주스",
|
"#Name": "토마토 주스",
|
||||||
"CookwareType:Enum": "JuiceMachine",
|
"CookwareKey:string": "item_environment_cookware_007",
|
||||||
"CookTime:int": 1,
|
"CookTime:int": 1,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_006",
|
"IngredientKey1:string": "item_ingredient_006",
|
||||||
@ -1009,7 +1450,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_drink_002",
|
"Id:string": "item_drink_002",
|
||||||
"#Name": "오렌지 주스",
|
"#Name": "오렌지 주스",
|
||||||
"CookwareType:Enum": "JuiceMachine",
|
"CookwareKey:string": "item_environment_cookware_007",
|
||||||
"CookTime:int": 1,
|
"CookTime:int": 1,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_023",
|
"IngredientKey1:string": "item_ingredient_023",
|
||||||
@ -1030,7 +1471,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_drink_003",
|
"Id:string": "item_drink_003",
|
||||||
"#Name": "여신의눈물",
|
"#Name": "여신의눈물",
|
||||||
"CookwareType:Enum": "Barrel",
|
"CookwareKey:string": "item_environment_cookware_008",
|
||||||
"CookTime:int": 3,
|
"CookTime:int": 3,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_008",
|
"IngredientKey1:string": "item_ingredient_008",
|
||||||
@ -1051,7 +1492,7 @@
|
|||||||
{
|
{
|
||||||
"Id:string": "item_drink_004",
|
"Id:string": "item_drink_004",
|
||||||
"#Name": "라벨블루",
|
"#Name": "라벨블루",
|
||||||
"CookwareType:Enum": "Barrel",
|
"CookwareKey:string": "item_environment_cookware_008",
|
||||||
"CookTime:int": 3,
|
"CookTime:int": 3,
|
||||||
"Price:int": 10,
|
"Price:int": 10,
|
||||||
"IngredientKey1:string": "item_ingredient_002",
|
"IngredientKey1:string": "item_ingredient_002",
|
||||||
@ -1093,7 +1534,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "item_ingredient_005",
|
"Id:string": "item_ingredient_005",
|
||||||
"#Name": "치킨닭 고기"
|
"#Name": "미정"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "item_ingredient_006",
|
"Id:string": "item_ingredient_006",
|
||||||
@ -1168,6 +1609,53 @@
|
|||||||
"#Name": "오렌지"
|
"#Name": "오렌지"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"CookwareData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별ID",
|
||||||
|
"#Name": "이름",
|
||||||
|
"CookwareType:Enum": "요리도구 타입"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_001",
|
||||||
|
"#Name": "냄비",
|
||||||
|
"CookwareType:Enum": "Pot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_002",
|
||||||
|
"#Name": "튀김",
|
||||||
|
"CookwareType:Enum": "Fryer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_003",
|
||||||
|
"#Name": "화로",
|
||||||
|
"CookwareType:Enum": "FirePit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_004",
|
||||||
|
"#Name": "",
|
||||||
|
"CookwareType:Enum": "CuttingBoard"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_005",
|
||||||
|
"#Name": "",
|
||||||
|
"CookwareType:Enum": "Griddle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_006",
|
||||||
|
"#Name": "",
|
||||||
|
"CookwareType:Enum": "MagicOven"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_007",
|
||||||
|
"#Name": "",
|
||||||
|
"CookwareType:Enum": "JuiceMachine"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "item_environment_cookware_008",
|
||||||
|
"#Name": "",
|
||||||
|
"CookwareType:Enum": "Barrel"
|
||||||
|
}
|
||||||
|
],
|
||||||
"TasteData": [
|
"TasteData": [
|
||||||
{
|
{
|
||||||
"Id:string": "식별ID",
|
"Id:string": "식별ID",
|
||||||
@ -1176,92 +1664,92 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Sweet",
|
"Id:string": "Sweet",
|
||||||
"#Name": "",
|
"#Name": "단맛",
|
||||||
"TasteType:Enum": "Sweet"
|
"TasteType:Enum": "Sweet"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Warm",
|
"Id:string": "Warm",
|
||||||
"#Name": "",
|
"#Name": "따뜻한",
|
||||||
"TasteType:Enum": "Warm"
|
"TasteType:Enum": "Warm"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Vegetable",
|
"Id:string": "Vegetable",
|
||||||
"#Name": "",
|
"#Name": "채류",
|
||||||
"TasteType:Enum": "Vegetable"
|
"TasteType:Enum": "Vegetable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Bitter",
|
"Id:string": "Bitter",
|
||||||
"#Name": "",
|
"#Name": "쓴맛",
|
||||||
"TasteType:Enum": "Bitter"
|
"TasteType:Enum": "Bitter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Salty",
|
"Id:string": "Salty",
|
||||||
"#Name": "",
|
"#Name": "짠맛",
|
||||||
"TasteType:Enum": "Salty"
|
"TasteType:Enum": "Salty"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Mild",
|
"Id:string": "Mild",
|
||||||
"#Name": "",
|
"#Name": "담백한",
|
||||||
"TasteType:Enum": "Mild"
|
"TasteType:Enum": "Mild"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Addictive",
|
"Id:string": "Addictive",
|
||||||
"#Name": "",
|
"#Name": "중독적인",
|
||||||
"TasteType:Enum": "Addictive"
|
"TasteType:Enum": "Addictive"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Sour",
|
"Id:string": "Sour",
|
||||||
"#Name": "",
|
"#Name": "신맛",
|
||||||
"TasteType:Enum": "Sour"
|
"TasteType:Enum": "Sour"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Savory",
|
"Id:string": "Savory",
|
||||||
"#Name": "",
|
"#Name": "고소한",
|
||||||
"TasteType:Enum": "Savory"
|
"TasteType:Enum": "Savory"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Meat",
|
"Id:string": "Meat",
|
||||||
"#Name": "",
|
"#Name": "육류",
|
||||||
"TasteType:Enum": "Meat"
|
"TasteType:Enum": "Meat"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "SuperHot",
|
"Id:string": "SuperHot",
|
||||||
"#Name": "",
|
"#Name": "핵불닭맛",
|
||||||
"TasteType:Enum": "SuperHot"
|
"TasteType:Enum": "SuperHot"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Fish",
|
"Id:string": "Fish",
|
||||||
"#Name": "",
|
"#Name": "어류",
|
||||||
"TasteType:Enum": "Fish"
|
"TasteType:Enum": "Fish"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "NoneDegree",
|
"Id:string": "NoneDegree",
|
||||||
"#Name": "",
|
"#Name": "도수가없는",
|
||||||
"TasteType:Enum": "NoneDegree"
|
"TasteType:Enum": "NoneDegree"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "Soda",
|
"Id:string": "Soda",
|
||||||
"#Name": "",
|
"#Name": "탄산",
|
||||||
"TasteType:Enum": "Soda"
|
"TasteType:Enum": "Soda"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "LowDegree",
|
"Id:string": "LowDegree",
|
||||||
"#Name": "",
|
"#Name": "도수가낮은",
|
||||||
"TasteType:Enum": "LowDegree"
|
"TasteType:Enum": "LowDegree"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "WoodFlavor",
|
"Id:string": "WoodFlavor",
|
||||||
"#Name": "",
|
"#Name": "나무향",
|
||||||
"TasteType:Enum": "WoodFlavor"
|
"TasteType:Enum": "WoodFlavor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "MiddleDegree",
|
"Id:string": "MiddleDegree",
|
||||||
"#Name": "",
|
"#Name": "도수가보통인",
|
||||||
"TasteType:Enum": "MiddleDegree"
|
"TasteType:Enum": "MiddleDegree"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "FruitFlavor",
|
"Id:string": "FruitFlavor",
|
||||||
"#Name": "",
|
"#Name": "과일향",
|
||||||
"TasteType:Enum": "FruitFlavor"
|
"TasteType:Enum": "FruitFlavor"
|
||||||
}
|
}
|
||||||
],
|
],
|
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 61a1a3168841b2843bdc42a2d7affc2f
|
guid: 26d67eeb92542fa4bb54e438ab5d3628
|
||||||
TextScriptImporter:
|
TextScriptImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
@ -1,5 +1,4 @@
|
|||||||
// <auto-generated> File: IngredientDataSo.cs
|
// <auto-generated>
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace DDD
|
namespace DDD
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
// <auto-generated>
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class LevelData : IId
|
||||||
|
{
|
||||||
|
/// <summary>식별번호</summary>
|
||||||
|
[Tooltip("식별번호")]
|
||||||
|
[field: SerializeField]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>등장 지역</summary>
|
||||||
|
[Tooltip("등장 지역")]
|
||||||
|
public string Area;
|
||||||
|
|
||||||
|
/// <summary>일반 손님 풀</summary>
|
||||||
|
[Tooltip("일반 손님 풀")]
|
||||||
|
public string CustomerPool;
|
||||||
|
|
||||||
|
/// <summary>스페셜 손님 풀</summary>
|
||||||
|
[Tooltip("스페셜 손님 풀")]
|
||||||
|
public string SpecialCustomerPool;
|
||||||
|
|
||||||
|
/// <summary>확정 스페셜 손님 수</summary>
|
||||||
|
[Tooltip("확정 스페셜 손님 수")]
|
||||||
|
public int FixSpecialCustomerCount;
|
||||||
|
|
||||||
|
/// <summary>추가 스페셜 손님 확률</summary>
|
||||||
|
[Tooltip("추가 스페셜 손님 확률")]
|
||||||
|
public int AddSpecialCustomerCount;
|
||||||
|
|
||||||
|
/// <summary>손님 리스폰 시간</summary>
|
||||||
|
[Tooltip("손님 리스폰 시간")]
|
||||||
|
public int CustomerRespawnTime;
|
||||||
|
|
||||||
|
/// <summary>손님 1명당 경험치</summary>
|
||||||
|
[Tooltip("손님 1명당 경험치")]
|
||||||
|
public int Exp;
|
||||||
|
|
||||||
|
/// <summary>주문 대기 인내심 카운트 시간</summary>
|
||||||
|
[Tooltip("주문 대기 인내심 카운트 시간")]
|
||||||
|
public int OrderTime;
|
||||||
|
|
||||||
|
/// <summary>주문 인내심 카운트 시간</summary>
|
||||||
|
[Tooltip("주문 인내심 카운트 시간")]
|
||||||
|
public int WaitTime;
|
||||||
|
|
||||||
|
/// <summary>식사 소요시간</summary>
|
||||||
|
[Tooltip("식사 소요시간")]
|
||||||
|
public int EatingTime;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 56f9c016bfc63a04280b30c71254c556
|
@ -0,0 +1,8 @@
|
|||||||
|
// <auto-generated>
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(fileName = "LevelDataSo", menuName = "GoogleSheet/LevelDataSo")]
|
||||||
|
public class LevelDataSo : DataSo<LevelData> { }
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4205a3f22a79fa74ba1cb5786c1bc13b
|
@ -1,20 +0,0 @@
|
|||||||
// <auto-generated>
|
|
||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DDD
|
|
||||||
{
|
|
||||||
[Serializable]
|
|
||||||
public class TasteData : IId
|
|
||||||
{
|
|
||||||
/// <summary>식별ID</summary>
|
|
||||||
[Tooltip("식별ID")]
|
|
||||||
[field: SerializeField]
|
|
||||||
public string Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>맛 종류</summary>
|
|
||||||
[Tooltip("맛 종류")]
|
|
||||||
public TasteType TasteType;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,64 +3,41 @@
|
|||||||
|
|
||||||
namespace DDD
|
namespace DDD
|
||||||
{
|
{
|
||||||
|
public enum CookwareType
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Barrel = 1,
|
||||||
|
CuttingBoard = 2,
|
||||||
|
FirePit = 3,
|
||||||
|
Fryer = 4,
|
||||||
|
Griddle = 5,
|
||||||
|
JuiceMachine = 6,
|
||||||
|
MagicOven = 7,
|
||||||
|
Pot = 8,
|
||||||
|
}
|
||||||
|
|
||||||
public enum ItemType
|
public enum ItemType
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Food = 1,
|
Drink = 1,
|
||||||
Ingredient = 2,
|
Environment = 2,
|
||||||
Environment = 3,
|
Food = 3,
|
||||||
Drink = 4,
|
Ingredient = 4,
|
||||||
Recipe = 5,
|
Recipe = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RecipeType
|
public enum RecipeType
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
FoodRecipe = 1,
|
DrinkRecipe = 1,
|
||||||
DrinkRecipe = 2,
|
FoodRecipe = 2,
|
||||||
}
|
|
||||||
|
|
||||||
public enum CookwareType
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Pot = 1,
|
|
||||||
Fryer = 2,
|
|
||||||
FirePit = 3,
|
|
||||||
CuttingBoard = 4,
|
|
||||||
Griddle = 5,
|
|
||||||
MagicOven = 6,
|
|
||||||
JuiceMachine = 7,
|
|
||||||
Barrel = 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TasteType
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Sweet = 1,
|
|
||||||
Warm = 2,
|
|
||||||
Vegetable = 3,
|
|
||||||
Bitter = 4,
|
|
||||||
Salty = 5,
|
|
||||||
Mild = 6,
|
|
||||||
Addictive = 7,
|
|
||||||
Sour = 8,
|
|
||||||
Savory = 9,
|
|
||||||
Meat = 10,
|
|
||||||
SuperHot = 11,
|
|
||||||
Fish = 12,
|
|
||||||
NoneDegree = 13,
|
|
||||||
Soda = 14,
|
|
||||||
LowDegree = 15,
|
|
||||||
WoodFlavor = 16,
|
|
||||||
MiddleDegree = 17,
|
|
||||||
FruitFlavor = 18,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum RendererType
|
public enum RendererType
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Sprite = 1,
|
Spine = 1,
|
||||||
Spine = 2,
|
Sprite = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,10 +58,419 @@
|
|||||||
"": "FruitFlavor"
|
"": "FruitFlavor"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"Test": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customers:string": "등장 손님",
|
||||||
|
"Test": 2352,
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": 0,
|
||||||
|
"Tests": "테스트, 테스트2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customers:string": "customer_001 | customer_002",
|
||||||
|
"Test": 3,
|
||||||
|
"Tests": "1 , 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customers:string": "customer_001 | customer_002 | customer_003",
|
||||||
|
"Test": 2,
|
||||||
|
"Tests": "5, 23,253"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": "435, 25"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers:string": "customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customers:string": "special_customer_001",
|
||||||
|
"Test": "",
|
||||||
|
"Tests": "111|234"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Test_view": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customers1": "등장 손님1",
|
||||||
|
"Customers2": "등장 손님2",
|
||||||
|
"Customers3": "등장 손님3",
|
||||||
|
"Customers4": "등장 손님4",
|
||||||
|
"Customers5": "등장 손님5",
|
||||||
|
"Customers6": "등장 손님6",
|
||||||
|
"Test": 2352,
|
||||||
|
"Tests1": "Tests1",
|
||||||
|
"Tests2": "Tests2",
|
||||||
|
"Tests3": "Tests3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 0,
|
||||||
|
"Tests1": "테스트",
|
||||||
|
"Tests2": "테스트2",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "customer_002",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 3,
|
||||||
|
"Tests1": 1,
|
||||||
|
"Tests2": 2,
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "customer_002",
|
||||||
|
"Customers3": "customer_003",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": 2,
|
||||||
|
"Tests1": 5,
|
||||||
|
"Tests2": 23,
|
||||||
|
"Tests3": 253
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": "",
|
||||||
|
"Tests2": "",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": 435,
|
||||||
|
"Tests2": 25,
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customers1": "customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": "",
|
||||||
|
"Tests2": "",
|
||||||
|
"Tests3": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customers1": "special_customer_001",
|
||||||
|
"Customers2": "",
|
||||||
|
"Customers3": "",
|
||||||
|
"Customers4": "",
|
||||||
|
"Customers5": "",
|
||||||
|
"Customers6": "",
|
||||||
|
"Test": "",
|
||||||
|
"Tests1": 111,
|
||||||
|
"Tests2": 234,
|
||||||
|
"Tests3": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CustomerPoolData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"CustomerLimitCount": "손님 최대 수",
|
||||||
|
"Customer1": "등장 손님1",
|
||||||
|
"Customer2": "등장 손님2",
|
||||||
|
"Customer3": "등장 손님3",
|
||||||
|
"Customer4": "등장 손님4",
|
||||||
|
"Customer5": "등장 손님5",
|
||||||
|
"Customer6": "등장 손님6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_001",
|
||||||
|
"CustomerLimitCount": 4,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_002",
|
||||||
|
"CustomerLimitCount": 7,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "customer_002",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_003",
|
||||||
|
"CustomerLimitCount": 9,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "customer_002",
|
||||||
|
"Customer3": " customer_003",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_004",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_005",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "customer_pool_006",
|
||||||
|
"CustomerLimitCount": 3,
|
||||||
|
"Customer1": "customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": "special_customer_pool_001",
|
||||||
|
"CustomerLimitCount": 1,
|
||||||
|
"Customer1": "special_customer_001",
|
||||||
|
"Customer2": "",
|
||||||
|
"Customer3": "",
|
||||||
|
"Customer4": "",
|
||||||
|
"Customer5": "",
|
||||||
|
"Customer6": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"LevelData": [
|
||||||
|
{
|
||||||
|
"Id:string": "식별번호",
|
||||||
|
"Area": "등장 지역",
|
||||||
|
"CustomerPool": "일반 손님 풀",
|
||||||
|
"SpecialCustomerPool": "스페셜 손님 풀",
|
||||||
|
"FixSpecialCustomerCount": "확정 스페셜 손님 수",
|
||||||
|
"AddSpecialCustomerCount": "추가 스페셜 손님 확률",
|
||||||
|
"CustomerRespawnTime": "손님 리스폰 시간",
|
||||||
|
"Exp": "손님 1명당 경험치",
|
||||||
|
"OrderTime": "주문 대기 인내심 카운트 시간",
|
||||||
|
"WaitTime": "주문 인내심 카운트 시간",
|
||||||
|
"EatingTime": "식사 소요시간"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 1,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_001",
|
||||||
|
"SpecialCustomerPool": "",
|
||||||
|
"FixSpecialCustomerCount": 0,
|
||||||
|
"AddSpecialCustomerCount": 0,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 2,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_002",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 1,
|
||||||
|
"AddSpecialCustomerCount": 10,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 3,
|
||||||
|
"Area": "Area1",
|
||||||
|
"CustomerPool": "customer_pool_003",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 2,
|
||||||
|
"AddSpecialCustomerCount": 30,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 4,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_004",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 5,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_005",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id:string": 6,
|
||||||
|
"Area": "Area2",
|
||||||
|
"CustomerPool": "customer_pool_006",
|
||||||
|
"SpecialCustomerPool": "special_customer_pool_001",
|
||||||
|
"FixSpecialCustomerCount": 3,
|
||||||
|
"AddSpecialCustomerCount": 50,
|
||||||
|
"CustomerRespawnTime": 6,
|
||||||
|
"Exp": 13,
|
||||||
|
"OrderTime": 30,
|
||||||
|
"WaitTime": 60,
|
||||||
|
"EatingTime": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"CustomerData": [
|
||||||
|
{
|
||||||
|
"Id": "식별번호",
|
||||||
|
"CustomerType": "손님 타입",
|
||||||
|
"#Name": "이름",
|
||||||
|
"SpineSkinKey": "스파인 스킨 키 값",
|
||||||
|
"FavoriteTaste1": "선호 맛1",
|
||||||
|
"FavoriteTaste2": "선호 맛2",
|
||||||
|
"FavoriteTaste3": "선호 맛3",
|
||||||
|
"FavoriteTaste4": "선호 맛4",
|
||||||
|
"FavoriteTaste5": "선호 맛5",
|
||||||
|
"FavoriteTaste6": "선호 맛6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_001",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령1",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_002",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령2",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "customer_003",
|
||||||
|
"CustomerType": "Normal",
|
||||||
|
"#Name": "유령3",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": "special_customer_001",
|
||||||
|
"CustomerType": "Special",
|
||||||
|
"#Name": "차이",
|
||||||
|
"SpineSkinKey": "",
|
||||||
|
"FavoriteTaste1": "",
|
||||||
|
"FavoriteTaste2": "",
|
||||||
|
"FavoriteTaste3": "",
|
||||||
|
"FavoriteTaste4": "",
|
||||||
|
"FavoriteTaste5": "",
|
||||||
|
"FavoriteTaste6": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
"ItemData": [
|
"ItemData": [
|
||||||
{
|
{
|
||||||
"Id": "식별번호",
|
"Id": "식별번호",
|
||||||
"ItemType:Enum": "아이템타입"
|
"ItemType:Enum": "아이템타입1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": "item_food_001",
|
"Id": "item_food_001",
|
||||||
@ -1125,7 +1534,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "item_ingredient_005",
|
"Id:string": "item_ingredient_005",
|
||||||
"#Name": "치킨닭 고기"
|
"#Name": "미정"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id:string": "item_ingredient_006",
|
"Id:string": "item_ingredient_006",
|
||||||
|
File diff suppressed because it is too large
Load Diff
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/CookwareDataSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/CookwareDataSo.asset
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/DrinkDataSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/DrinkDataSo.asset
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/EnvironmentDataSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/EnvironmentDataSo.asset
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/FoodDataSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/FoodDataSo.asset
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/IngredientDataSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/IngredientDataSo.asset
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/ItemDataSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/ItemDataSo.asset
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/LevelDataSo.asset
(Stored with Git LFS)
Normal file
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/LevelDataSo.asset
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3392661ff91138a4991ec360e86907cb
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/RecipeDataSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/RecipeDataSo.asset
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/TasteDataSo.asset
(Stored with Git LFS)
BIN
Assets/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated/So/TasteDataSo.asset
(Stored with Git LFS)
Binary file not shown.
@ -1,66 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using System.IO;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.AddressableAssets;
|
|
||||||
using UnityEditor.AddressableAssets.Settings;
|
|
||||||
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public static class GoogleSheetAddressableAutoSetup
|
|
||||||
{
|
|
||||||
private const string TargetGroupName = "GoogleSheetSo_Group";
|
|
||||||
private const string TargetLabel = "GoogleSheetSo";
|
|
||||||
|
|
||||||
public static void AutoRegisterSo(string assetPath)
|
|
||||||
{
|
|
||||||
var settings = AddressableAssetSettingsDefaultObject.Settings;
|
|
||||||
if (settings == null)
|
|
||||||
{
|
|
||||||
Debug.LogError("Addressable 설정을 찾을 수 없습니다.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
|
||||||
if (string.IsNullOrEmpty(guid)) return;
|
|
||||||
|
|
||||||
// 그룹 가져오기 또는 생성
|
|
||||||
var group = settings.FindGroup(TargetGroupName);
|
|
||||||
if (group == null)
|
|
||||||
{
|
|
||||||
group = settings.CreateGroup(TargetGroupName, false, false, false, null,
|
|
||||||
typeof(BundledAssetGroupSchema), typeof(ContentUpdateGroupSchema));
|
|
||||||
|
|
||||||
var bundledSchema = group.GetSchema<BundledAssetGroupSchema>();
|
|
||||||
bundledSchema.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackTogether;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 엔트리 추가
|
|
||||||
var entry = settings.FindAssetEntry(guid);
|
|
||||||
if (entry == null)
|
|
||||||
{
|
|
||||||
entry = settings.CreateOrMoveEntry(guid, group);
|
|
||||||
}
|
|
||||||
else if (entry.parentGroup != group)
|
|
||||||
{
|
|
||||||
settings.MoveEntry(entry, group);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Address 설정
|
|
||||||
string name = Path.GetFileNameWithoutExtension(assetPath);
|
|
||||||
entry.address = name;
|
|
||||||
|
|
||||||
// Label 설정
|
|
||||||
if (!entry.labels.Contains(TargetLabel))
|
|
||||||
{
|
|
||||||
entry.SetLabel(TargetLabel, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 저장
|
|
||||||
EditorUtility.SetDirty(settings);
|
|
||||||
settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, entry, true);
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
|
|
||||||
Debug.Log($"✅ Addressables에 등록 완료: {name}, 그룹: {TargetGroupName}, 라벨: {TargetLabel}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 91161e8df06b9734ca03d579aceaa508
|
|
@ -1,30 +0,0 @@
|
|||||||
// GoogleSheetChangeLog.cs
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
[CreateAssetMenu(fileName = "GoogleSheetChangeLog", menuName = "GoogleSheet/ChangeLog", order = 0)]
|
|
||||||
public class GoogleSheetChangeLog : ScriptableObject
|
|
||||||
{
|
|
||||||
[Serializable]
|
|
||||||
public class LogEntry
|
|
||||||
{
|
|
||||||
public string Editor;
|
|
||||||
public string Timestamp;
|
|
||||||
[TextArea(5, 20)] public string JsonSnapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
[SerializeField] private List<LogEntry> _logs = new();
|
|
||||||
public List<LogEntry> Logs => _logs;
|
|
||||||
|
|
||||||
public int MaxLogs = 100;
|
|
||||||
|
|
||||||
public void AddEntry(LogEntry entry)
|
|
||||||
{
|
|
||||||
if (_logs.Count >= MaxLogs)
|
|
||||||
{
|
|
||||||
_logs.RemoveAt(0);
|
|
||||||
}
|
|
||||||
_logs.Add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class GoogleSheetDiff
|
|
||||||
{
|
|
||||||
public string Sheet;
|
|
||||||
public string Field;
|
|
||||||
public int RowIndex;
|
|
||||||
public string OldValue;
|
|
||||||
public string NewValue;
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
public static class GoogleSheetDiffHelper
|
|
||||||
{
|
|
||||||
public static List<GoogleSheetDiff> CompareJsonDiff(string oldJson, string newJson)
|
|
||||||
{
|
|
||||||
var diffs = new List<GoogleSheetDiff>();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(oldJson) || string.IsNullOrEmpty(newJson))
|
|
||||||
return diffs;
|
|
||||||
|
|
||||||
var oldObj = JObject.Parse(oldJson);
|
|
||||||
var newObj = JObject.Parse(newJson);
|
|
||||||
|
|
||||||
foreach (var sheet in newObj)
|
|
||||||
{
|
|
||||||
var sheetName = sheet.Key;
|
|
||||||
if (!oldObj.TryGetValue(sheetName, out var oldSheetToken))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var oldArray = oldSheetToken as JArray;
|
|
||||||
var newArray = sheet.Value as JArray;
|
|
||||||
|
|
||||||
for (int i = 1; i < newArray.Count; i++)
|
|
||||||
{
|
|
||||||
if (i >= oldArray.Count)
|
|
||||||
break;
|
|
||||||
|
|
||||||
var newRow = (JObject)newArray[i];
|
|
||||||
var oldRow = (JObject)oldArray[i];
|
|
||||||
|
|
||||||
foreach (var prop in newRow.Properties())
|
|
||||||
{
|
|
||||||
var field = prop.Name;
|
|
||||||
string newValue = prop.Value.ToString();
|
|
||||||
string oldValue = oldRow.TryGetValue(field, out var oldVal) ? oldVal.ToString() : "";
|
|
||||||
|
|
||||||
if (oldValue != newValue)
|
|
||||||
{
|
|
||||||
diffs.Add(new GoogleSheetDiff
|
|
||||||
{
|
|
||||||
Sheet = sheetName,
|
|
||||||
Field = field,
|
|
||||||
RowIndex = i,
|
|
||||||
OldValue = oldValue,
|
|
||||||
NewValue = newValue
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return diffs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GenerateDiff(string oldJson, string newJson)
|
|
||||||
{
|
|
||||||
var diffs = CompareJsonDiff(oldJson, newJson);
|
|
||||||
if (diffs.Count == 0)
|
|
||||||
return "No differences found.";
|
|
||||||
|
|
||||||
var sb = new System.Text.StringBuilder();
|
|
||||||
sb.AppendLine("[GoogleSheetManager] 변경된 필드들:");
|
|
||||||
|
|
||||||
foreach (var diff in diffs)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{diff.Sheet} / Row {diff.RowIndex} / {diff.Field} : '{diff.OldValue}' → '{diff.NewValue}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b1cb07de998538442b14e113ff8da86e
|
|
@ -1,69 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
public class GoogleSheetDiffViewer : EditorWindow
|
|
||||||
{
|
|
||||||
private List<GoogleSheetDiff> _diffs;
|
|
||||||
private bool _isReversed; // true: 현재 → 선택버전, false: 변경 전 → 변경 후
|
|
||||||
|
|
||||||
private Vector2 _scroll;
|
|
||||||
|
|
||||||
public static void ShowWindow(List<GoogleSheetDiff> diffs, bool isReversed = false)
|
|
||||||
{
|
|
||||||
var window = GetWindow<GoogleSheetDiffViewer>("Google Sheet 변경점");
|
|
||||||
window._diffs = diffs;
|
|
||||||
window._isReversed = isReversed;
|
|
||||||
window.Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGUI()
|
|
||||||
{
|
|
||||||
EditorGUILayout.LabelField("변경된 항목", EditorStyles.boldLabel);
|
|
||||||
EditorGUILayout.Space();
|
|
||||||
|
|
||||||
if (_diffs == null || _diffs.Count == 0)
|
|
||||||
{
|
|
||||||
EditorGUILayout.HelpBox("변경 사항이 없습니다.", MessageType.Info);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 헤더
|
|
||||||
EditorGUILayout.BeginHorizontal("box");
|
|
||||||
EditorGUILayout.LabelField("시트", EditorStyles.boldLabel, GUILayout.Width(80));
|
|
||||||
EditorGUILayout.LabelField("행", EditorStyles.boldLabel, GUILayout.Width(40));
|
|
||||||
EditorGUILayout.LabelField("필드", EditorStyles.boldLabel, GUILayout.Width(140));
|
|
||||||
|
|
||||||
GUIStyle oldStyle = new GUIStyle(EditorStyles.label);
|
|
||||||
oldStyle.normal.textColor = Color.green;
|
|
||||||
EditorGUILayout.LabelField(_isReversed ? "현재 버전" : "변경 전", oldStyle, GUILayout.Width(100));
|
|
||||||
|
|
||||||
GUIStyle newStyle = new GUIStyle(EditorStyles.label);
|
|
||||||
newStyle.normal.textColor = new Color(0.3f, 0.75f, 1.0f);
|
|
||||||
EditorGUILayout.LabelField(_isReversed ? "선택한 버전" : "변경 후", newStyle, GUILayout.Width(100));
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
_scroll = EditorGUILayout.BeginScrollView(_scroll);
|
|
||||||
|
|
||||||
foreach (var diff in _diffs)
|
|
||||||
{
|
|
||||||
EditorGUILayout.BeginHorizontal("box");
|
|
||||||
|
|
||||||
EditorGUILayout.LabelField(diff.Sheet, GUILayout.Width(80));
|
|
||||||
EditorGUILayout.LabelField(diff.RowIndex.ToString(), GUILayout.Width(40));
|
|
||||||
EditorGUILayout.LabelField(diff.Field, GUILayout.Width(140));
|
|
||||||
|
|
||||||
string left = _isReversed ? diff.NewValue : diff.OldValue;
|
|
||||||
string right = _isReversed ? diff.OldValue : diff.NewValue;
|
|
||||||
|
|
||||||
EditorGUILayout.LabelField(left, oldStyle, GUILayout.Width(100));
|
|
||||||
EditorGUILayout.LabelField(right, newStyle, GUILayout.Width(100));
|
|
||||||
|
|
||||||
EditorGUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.EndScrollView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,53 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public static class GoogleSheetFetchHelper
|
|
||||||
{
|
|
||||||
public static List<GoogleSheetDiff> CompareJsonDiff(string oldJson, string newJson)
|
|
||||||
{
|
|
||||||
var result = new List<GoogleSheetDiff>();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(oldJson) || string.IsNullOrEmpty(newJson))
|
|
||||||
return result;
|
|
||||||
|
|
||||||
var oldObj = JObject.Parse(oldJson);
|
|
||||||
var newObj = JObject.Parse(newJson);
|
|
||||||
|
|
||||||
foreach (var sheet in newObj)
|
|
||||||
{
|
|
||||||
if (!oldObj.TryGetValue(sheet.Key, out var oldSheetData))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var newSheetData = (JArray)sheet.Value;
|
|
||||||
var oldSheetArray = (JArray)oldSheetData;
|
|
||||||
|
|
||||||
int minCount = Mathf.Min(oldSheetArray.Count, newSheetData.Count);
|
|
||||||
|
|
||||||
for (int i = 1; i < minCount; i++)
|
|
||||||
{
|
|
||||||
var oldRow = (JObject)oldSheetArray[i];
|
|
||||||
var newRow = (JObject)newSheetData[i];
|
|
||||||
|
|
||||||
foreach (var prop in newRow.Properties())
|
|
||||||
{
|
|
||||||
string oldVal = oldRow.TryGetValue(prop.Name, out var val) ? val.ToString() : "";
|
|
||||||
string newVal = prop.Value.ToString();
|
|
||||||
|
|
||||||
if (oldVal != newVal)
|
|
||||||
{
|
|
||||||
result.Add(new GoogleSheetDiff
|
|
||||||
{
|
|
||||||
Sheet = sheet.Key,
|
|
||||||
Field = prop.Name,
|
|
||||||
RowIndex = i + 1,
|
|
||||||
OldValue = oldVal,
|
|
||||||
NewValue = newVal
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e3062282d3af306458153938166b72ce
|
|
@ -1,906 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections;
|
|
||||||
using UnityEngine;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Sirenix.OdinInspector;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine.AddressableAssets;
|
|
||||||
using ColorUtility = UnityEngine.ColorUtility;
|
|
||||||
|
|
||||||
public class GoogleSheetManager : Singleton<GoogleSheetManager>
|
|
||||||
{
|
|
||||||
[BoxGroup("기본 설정")]
|
|
||||||
[SerializeField, Tooltip("true: google sheet, false: local json")]
|
|
||||||
private bool _isAccessGoogleSheet = true;
|
|
||||||
|
|
||||||
[BoxGroup("기본 설정")]
|
|
||||||
[SerializeField, Tooltip("구글 시트 -> 확장 프로그램 -> Apps Script -> 새 배포(웹 앱) or 배포 관리 -> 웹 앱 URL(~~~/exec)")]
|
|
||||||
private string _googleSheetUrl;
|
|
||||||
|
|
||||||
[BoxGroup("기본 설정")]
|
|
||||||
[SerializeField, Tooltip("기본 네임 스페이스")]
|
|
||||||
private string _namespace = "DDD";
|
|
||||||
|
|
||||||
[BoxGroup("기본 설정")]
|
|
||||||
[SerializeField, Tooltip("코드/Enum/So 자동 생성 + 데이터 반영 시트")]
|
|
||||||
private List<string> _autoCreateSheets = new();
|
|
||||||
|
|
||||||
[BoxGroup("기본 설정")]
|
|
||||||
[SerializeField, Tooltip("기존 Data/So 유지, SO 데이터만 동기화 시트")]
|
|
||||||
private List<string> _soSyncSheets = new();
|
|
||||||
|
|
||||||
[BoxGroup("기본 설정")]
|
|
||||||
[SerializeField, Tooltip("Class, Json, So 생성 위치 \"/GenerateGoogleSheet\"")]
|
|
||||||
private string _generateFolderPath = "/_DDD/_Scripts/GenerateGoogleSheet/AutoCreated";
|
|
||||||
|
|
||||||
[BoxGroup("버전 복구")]
|
|
||||||
[SerializeField, Tooltip("현재 사용중인 버전"), ReadOnly, UsedImplicitly]
|
|
||||||
private string _currentVersion;
|
|
||||||
|
|
||||||
[BoxGroup("버전 복구")]
|
|
||||||
[SerializeField, ValueDropdown(nameof(GetVersionOptions))]
|
|
||||||
private int _restoreIndex;
|
|
||||||
|
|
||||||
[BoxGroup("데이터 변경"), LabelText("수정자 이름")]
|
|
||||||
[SerializeField, Required("반드시 수정자 이름을 입력해야 합니다\n이력을 남길 때 표시될 사용자 이름입니다.")]
|
|
||||||
private string _editorName;
|
|
||||||
|
|
||||||
private string BaseFullPath => $"{Application.dataPath}{_generateFolderPath}";
|
|
||||||
private string BaseAssetPath => $"Assets{_generateFolderPath}";
|
|
||||||
private string JsonFullPath => $"{BaseFullPath}/GoogleSheetJson.json";
|
|
||||||
private string ChangeLogAssetPath => $"{BaseAssetPath}/Logs/GoogleSheetChangeLog.asset";
|
|
||||||
private string BackupFullPath => $"{BaseFullPath}/BackUps";
|
|
||||||
private string ClassedFullPath => $"{BaseAssetPath}/Classes";
|
|
||||||
|
|
||||||
private string[] _availSheetArray;
|
|
||||||
private string _json;
|
|
||||||
private bool _isCreatingSo;
|
|
||||||
|
|
||||||
[SerializeField, ReadOnly]
|
|
||||||
private bool _refreshTrigger;
|
|
||||||
|
|
||||||
private bool _alreadyCreatedSo;
|
|
||||||
|
|
||||||
private bool IsAuto(string name) => _autoCreateSheets.Contains(name);
|
|
||||||
private bool IsSync(string name) => _soSyncSheets.Contains(name);
|
|
||||||
private bool IsSelected(string name) => IsAuto(name) || IsSync(name);
|
|
||||||
|
|
||||||
[BoxGroup("데이터 변경")]
|
|
||||||
[Button("데이터 최신화"), EnableIf(nameof(CanFetchData))]
|
|
||||||
private async Task FetchGoogleSheet()
|
|
||||||
{
|
|
||||||
// 0) 이전 원본 JSON
|
|
||||||
var prevLog = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(ChangeLogAssetPath);
|
|
||||||
string previousJson = prevLog?.Logs.LastOrDefault()?.JsonSnapshot ?? "";
|
|
||||||
|
|
||||||
// 1) 최신 원본 JSON 로드 (전체 시트)
|
|
||||||
if (_isAccessGoogleSheet)
|
|
||||||
{
|
|
||||||
if (!IsValidGoogleSheetUrl(_googleSheetUrl))
|
|
||||||
{
|
|
||||||
Debug.LogError("Google Sheet URL이 유효하지 않습니다.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.Log("구글 시트 데이터 읽는 중...");
|
|
||||||
_json = await LoadDataGoogleSheet(_googleSheetUrl);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log("Local Json 파일 읽는 중...");
|
|
||||||
_json = LoadDataLocalJson();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_json))
|
|
||||||
{
|
|
||||||
Debug.LogWarning("Json is null/empty. 최신화 실패");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) Diff/로그는 '전체 JSON' 기준
|
|
||||||
var diffs = GoogleSheetFetchHelper.CompareJsonDiff(previousJson, _json);
|
|
||||||
if (diffs.Count > 0)
|
|
||||||
GoogleSheetDiffViewer.ShowWindow(diffs);
|
|
||||||
|
|
||||||
// 3) 워크 파일로 전체 JSON 저장(변경시만)
|
|
||||||
bool savedJson = SaveFileOrSkip(JsonFullPath, _json);
|
|
||||||
|
|
||||||
// 4) 클래스 생성 (auto만, 파일 없을 때만 생성)
|
|
||||||
bool createdScripts = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
createdScripts = GenerateClassFilesPerSheet(_json);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[GoogleSheetManager] 클래스 파일 생성 중 오류: {e.Message}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5) 로그/백업은 전체 JSON 기준으로 변경시에만 기록
|
|
||||||
if (!string.IsNullOrEmpty(previousJson))
|
|
||||||
{
|
|
||||||
if (!previousJson.Equals(_json))
|
|
||||||
SaveChangeLog(_json);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 첫 기록
|
|
||||||
SaveChangeLog(_json);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6) 새 스크립트가 생겼다면 컴파일 완료 대기
|
|
||||||
if (createdScripts)
|
|
||||||
{
|
|
||||||
await WaitUntilScriptsReady();
|
|
||||||
await Task.Delay(100); // 도메인 리로드 직후 안정화 여유
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7) SO 동기화는 항상 수행 (변경 없어도)
|
|
||||||
bool ok = await CreateGoogleSheetSoAsync();
|
|
||||||
if (!ok) Debug.LogWarning("SO 동기화 중 일부 실패가 있었습니다.");
|
|
||||||
|
|
||||||
// 8) 필요시 마무리 리프레시
|
|
||||||
if (savedJson || createdScripts || diffs.Count > 0)
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task WaitUntilScriptsReady()
|
|
||||||
{
|
|
||||||
// 스크립트 생성 직후 컴파일이 끝날 때까지 대기
|
|
||||||
while (EditorApplication.isCompiling)
|
|
||||||
await Task.Delay(150);
|
|
||||||
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CanFetchData()
|
|
||||||
{
|
|
||||||
return !string.IsNullOrWhiteSpace(_editorName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Json 로그 저장
|
|
||||||
/// </summary>
|
|
||||||
private void SaveChangeLog(string json)
|
|
||||||
{
|
|
||||||
string logsDirectory = Path.GetDirectoryName(ChangeLogAssetPath);
|
|
||||||
if (!Directory.Exists(logsDirectory))
|
|
||||||
{
|
|
||||||
if (logsDirectory != null)
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(logsDirectory);
|
|
||||||
AssetDatabase.ImportAsset(logsDirectory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var log = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(ChangeLogAssetPath);
|
|
||||||
if (log == null)
|
|
||||||
{
|
|
||||||
log = ScriptableObject.CreateInstance<GoogleSheetChangeLog>();
|
|
||||||
AssetDatabase.CreateAsset(log, ChangeLogAssetPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
string previousJson = log.Logs.Count > 0 ? log.Logs[^1].JsonSnapshot : null;
|
|
||||||
|
|
||||||
// 차이 비교
|
|
||||||
if (!string.IsNullOrEmpty(previousJson))
|
|
||||||
{
|
|
||||||
string diffResult = GoogleSheetDiffHelper.GenerateDiff(previousJson, json);
|
|
||||||
Debug.Log(diffResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
string saveTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
||||||
string versionLabel = $"{log.Logs.Count} - {saveTime} by {_editorName}";
|
|
||||||
|
|
||||||
_currentVersion = versionLabel;
|
|
||||||
log.Logs.Add(new GoogleSheetChangeLog.LogEntry
|
|
||||||
{
|
|
||||||
Editor = _editorName,
|
|
||||||
Timestamp = saveTime,
|
|
||||||
JsonSnapshot = json
|
|
||||||
});
|
|
||||||
|
|
||||||
EditorUtility.SetDirty(log);
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
SaveJsonBackup(json, saveTime);
|
|
||||||
_editorName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Json 백업
|
|
||||||
/// </summary>
|
|
||||||
private void SaveJsonBackup(string json, string saveTime)
|
|
||||||
{
|
|
||||||
string safeSaveTime = saveTime.Replace(":", "-"); // 윈도우 파일 이름 안전 처리
|
|
||||||
|
|
||||||
if (!Directory.Exists(BackupFullPath))
|
|
||||||
Directory.CreateDirectory(BackupFullPath);
|
|
||||||
|
|
||||||
string fileName = $"{safeSaveTime} by {_editorName}.json";
|
|
||||||
string filePath = Path.Combine(BackupFullPath, fileName);
|
|
||||||
|
|
||||||
File.WriteAllText(filePath, json);
|
|
||||||
}
|
|
||||||
|
|
||||||
[BoxGroup("버전 복구")]
|
|
||||||
[Button("선택한 버전과 현재 비교")]
|
|
||||||
private void CompareWithSelectedVersion()
|
|
||||||
{
|
|
||||||
var log = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(ChangeLogAssetPath);
|
|
||||||
if (log == null || _restoreIndex < 0 || _restoreIndex >= log.Logs.Count)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("비교할 수 있는 로그가 없습니다.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string restoreJson = log.Logs[_restoreIndex].JsonSnapshot;
|
|
||||||
string currentJson = File.Exists(JsonFullPath) ? File.ReadAllText(JsonFullPath) : "";
|
|
||||||
|
|
||||||
List<GoogleSheetDiff> diffs = GoogleSheetFetchHelper.CompareJsonDiff(currentJson, restoreJson);
|
|
||||||
|
|
||||||
if (diffs.Count > 0)
|
|
||||||
{
|
|
||||||
GoogleSheetDiffViewer.ShowWindow(diffs, true); // 현재 → 선택 버전
|
|
||||||
Debug.Log("[GoogleSheetManager] 선택한 버전과 현재 버전 간의 변경점을 표시합니다.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log("[GoogleSheetManager] 변경점 없음.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[BoxGroup("버전 복구")]
|
|
||||||
[Button("선택한 버전으로 복구")]
|
|
||||||
private async Task RestoreSelectedVersion()
|
|
||||||
{
|
|
||||||
var log = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(ChangeLogAssetPath);
|
|
||||||
if (log == null || _restoreIndex < 0 || _restoreIndex >= log.Logs.Count)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("복원할 수 있는 로그가 없습니다.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string restoreJson = log.Logs[_restoreIndex].JsonSnapshot;
|
|
||||||
string currentJson = File.Exists(JsonFullPath) ? await File.ReadAllTextAsync(JsonFullPath) : "";
|
|
||||||
|
|
||||||
var diffs = GoogleSheetFetchHelper.CompareJsonDiff(currentJson, restoreJson);
|
|
||||||
if (diffs.Count > 0)
|
|
||||||
GoogleSheetDiffViewer.ShowWindow(diffs);
|
|
||||||
|
|
||||||
_json = restoreJson;
|
|
||||||
SaveFileOrSkip(JsonFullPath, _json);
|
|
||||||
await CreateGoogleSheetSoAsync();
|
|
||||||
|
|
||||||
_currentVersion = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
||||||
Debug.Log($"[{log.Logs[_restoreIndex].Editor}]의 버전으로 복원 완료");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 버전 로그 드롭다운 함수
|
|
||||||
/// </summary>
|
|
||||||
private IEnumerable<ValueDropdownItem<int>> GetVersionOptions()
|
|
||||||
{
|
|
||||||
var log = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(ChangeLogAssetPath);
|
|
||||||
if (log == null)
|
|
||||||
yield break;
|
|
||||||
|
|
||||||
for (int i = 0; i < log.Logs.Count; i++)
|
|
||||||
{
|
|
||||||
yield return new ValueDropdownItem<int>($"{i} - {log.Logs[i].Timestamp} by {log.Logs[i].Editor}", i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 구글 시트 데이터 읽어오기
|
|
||||||
/// </summary>
|
|
||||||
private async Task<string> LoadDataGoogleSheet(string url)
|
|
||||||
{
|
|
||||||
// 네트워크가 느리거나 프록시/방화벽 영향 받는 환경에서 멈춤 방지
|
|
||||||
var handler = new HttpClientHandler
|
|
||||||
{
|
|
||||||
// 사내 프록시/보안 툴 때문에 멈출 수 있으면 필요에 따라 끄기
|
|
||||||
UseProxy = true, // 필요하면 false 로 바꿔 테스트
|
|
||||||
};
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler)
|
|
||||||
{
|
|
||||||
Timeout = TimeSpan.FromSeconds(20) // ← 핵심: 타임아웃
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Debug.Log("[GSM] HTTP GET start");
|
|
||||||
var resp = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
|
||||||
Debug.Log($"[GSM] HTTP status: {(int)resp.StatusCode} {resp.ReasonPhrase}");
|
|
||||||
|
|
||||||
resp.EnsureSuccessStatusCode(); // 2xx 아니면 예외
|
|
||||||
|
|
||||||
var text = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
Debug.Log($"[GSM] HTTP OK, length={text?.Length ?? 0}");
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
catch (TaskCanceledException)
|
|
||||||
{
|
|
||||||
Debug.LogError("[GSM] 요청이 타임아웃되었습니다. URL이 열리는지 브라우저에서 먼저 확인해보세요.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (HttpRequestException e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[GSM] HTTP 오류: {e.Message}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[GSM] 예기치 못한 오류: {e}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// jSON 데이터 파일 읽어오기
|
|
||||||
/// </summary>
|
|
||||||
private string LoadDataLocalJson()
|
|
||||||
{
|
|
||||||
if (File.Exists(JsonFullPath))
|
|
||||||
{
|
|
||||||
return File.ReadAllText(JsonFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.Log($"Json 파일이 존재하지 않습니다\n{JsonFullPath}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 파일 생성 및 비교
|
|
||||||
/// </summary>
|
|
||||||
private bool SaveFileOrSkip(string path, string contents)
|
|
||||||
{
|
|
||||||
string directoryPath = Path.GetDirectoryName(path);
|
|
||||||
if (!Directory.Exists(directoryPath))
|
|
||||||
{
|
|
||||||
if (directoryPath != null) Directory.CreateDirectory(directoryPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (File.Exists(path) && File.ReadAllText(path).Equals(contents))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
File.WriteAllText(path, contents);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 유효한 구글 웹 앱 URL인지 확인
|
|
||||||
/// </summary>
|
|
||||||
private bool IsValidGoogleSheetUrl(string url)
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(url)
|
|
||||||
&& url.StartsWith("https://script.google.com/macros/")
|
|
||||||
&& url.EndsWith("/exec");
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool GenerateClassFilesPerSheet(string jsonInput)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AssetDatabase.StartAssetEditing();
|
|
||||||
EditorApplication.LockReloadAssemblies();
|
|
||||||
AssetDatabase.DisallowAutoRefresh();
|
|
||||||
bool createdAny = false;
|
|
||||||
var root = JObject.Parse(jsonInput);
|
|
||||||
|
|
||||||
// 1) Enum 후보 수집 (auto 시트만)
|
|
||||||
var enumCandidates = new Dictionary<string, HashSet<string>>(StringComparer.Ordinal);
|
|
||||||
|
|
||||||
foreach (var pair in root)
|
|
||||||
{
|
|
||||||
string className = pair.Key;
|
|
||||||
if (!IsAuto(className)) continue;
|
|
||||||
|
|
||||||
var items = pair.Value as JArray;
|
|
||||||
if (items == null || items.Count < 2) continue;
|
|
||||||
|
|
||||||
for (int i = 1; i < items.Count; i++)
|
|
||||||
{
|
|
||||||
foreach (var prop in ((JObject)items[i]).Properties())
|
|
||||||
{
|
|
||||||
string raw = prop.Name;
|
|
||||||
if (raw.StartsWith("#")) continue;
|
|
||||||
|
|
||||||
string enumType = null;
|
|
||||||
if (raw.Contains(":Enum"))
|
|
||||||
{
|
|
||||||
// 단일 필드 Enum: Cookware:Enum -> enumType = "Cookware"
|
|
||||||
enumType = raw.Split(':')[0];
|
|
||||||
}
|
|
||||||
else if (raw.Contains(":") && raw.EndsWith("_Enum"))
|
|
||||||
{
|
|
||||||
// 공통 Enum: Taste1:Taste_Enum -> enumType = "Taste"
|
|
||||||
enumType = raw.Split(':')[1].Replace("_Enum", "");
|
|
||||||
}
|
|
||||||
else if (raw.Contains(":NativeEnum"))
|
|
||||||
{
|
|
||||||
continue; // 네이티브 enum은 자동 생성 대상 아님
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(enumType)) continue;
|
|
||||||
|
|
||||||
string enumValue = NormalizeEnumKey(prop.Value?.ToString() ?? "");
|
|
||||||
if (!enumCandidates.TryGetValue(enumType, out var set))
|
|
||||||
{
|
|
||||||
set = new HashSet<string>(StringComparer.Ordinal);
|
|
||||||
enumCandidates.Add(enumType, set);
|
|
||||||
}
|
|
||||||
|
|
||||||
set.Add(enumValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) EnumTypes.cs 생성/갱신 (자동 파일이므로 덮어써도 안전)
|
|
||||||
var enumPath = $"{BaseAssetPath}/EnumTypes.cs";
|
|
||||||
File.WriteAllText(enumPath, BuildEnumCode(enumCandidates));
|
|
||||||
AssetDatabase.ImportAsset(enumPath);
|
|
||||||
|
|
||||||
// 3) 클래스/So 생성 (auto만, 파일이 없을 때만)
|
|
||||||
if (!Directory.Exists(ClassedFullPath))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(ClassedFullPath);
|
|
||||||
AssetDatabase.ImportAsset(ClassedFullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var pair in root)
|
|
||||||
{
|
|
||||||
string className = pair.Key;
|
|
||||||
if (!IsAuto(className)) continue;
|
|
||||||
|
|
||||||
var items = pair.Value as JArray;
|
|
||||||
if (items == null || items.Count < 2) continue;
|
|
||||||
|
|
||||||
string dataPath = $"{ClassedFullPath}/{className}.cs";
|
|
||||||
string soPath = $"{ClassedFullPath}/{className}So.cs";
|
|
||||||
|
|
||||||
if (!File.Exists(dataPath))
|
|
||||||
{
|
|
||||||
File.WriteAllText(dataPath, GenerateDataClassCode(className, items));
|
|
||||||
AssetDatabase.ImportAsset(dataPath);
|
|
||||||
createdAny = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(soPath))
|
|
||||||
{
|
|
||||||
File.WriteAllText(soPath, GenerateSoClassCode(className));
|
|
||||||
AssetDatabase.ImportAsset(soPath);
|
|
||||||
createdAny = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return createdAny;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AssetDatabase.StopAssetEditing();
|
|
||||||
EditorApplication.UnlockReloadAssemblies();
|
|
||||||
AssetDatabase.AllowAutoRefresh();
|
|
||||||
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); // 마지막에 1회만
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string BuildEnumCode(Dictionary<string, HashSet<string>> enums)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.AppendLine("// <auto-generated>");
|
|
||||||
sb.AppendLine("using System;");
|
|
||||||
sb.AppendLine();
|
|
||||||
sb.AppendLine($"namespace {_namespace}");
|
|
||||||
sb.AppendLine("{");
|
|
||||||
|
|
||||||
foreach (var kv in enums)
|
|
||||||
{
|
|
||||||
sb.AppendLine($" public enum {kv.Key}");
|
|
||||||
sb.AppendLine(" {");
|
|
||||||
sb.AppendLine(" None = 0,");
|
|
||||||
int i = 1;
|
|
||||||
foreach (var val in kv.Value)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(val) && val != "None")
|
|
||||||
sb.AppendLine($" {val} = {i++},");
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.AppendLine(" }");
|
|
||||||
sb.AppendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.AppendLine("}");
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenerateSoClassCode(string className)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
$"// <auto-generated> File: {className}So.cs\n" +
|
|
||||||
"using System.Collections.Generic;\n" +
|
|
||||||
"using UnityEngine;\n\n" +
|
|
||||||
$"namespace {_namespace}\n" +
|
|
||||||
$"{{\n" +
|
|
||||||
$" [CreateAssetMenu(fileName = \"{className}So\", menuName = \"GoogleSheet/{className}So\")]\n" +
|
|
||||||
$" public class {className}So : DataSo<{className}> {{ }}\n" +
|
|
||||||
$"}}";
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenerateDataClassCode(string className, JArray items)
|
|
||||||
{
|
|
||||||
var commentRow = (JObject)items[0];
|
|
||||||
var sampleRow = (JObject)items[1];
|
|
||||||
|
|
||||||
StringBuilder sb = new();
|
|
||||||
sb.AppendLine("// <auto-generated>");
|
|
||||||
sb.AppendLine("using System;");
|
|
||||||
sb.AppendLine("using UnityEngine;");
|
|
||||||
sb.AppendLine();
|
|
||||||
sb.AppendLine($"namespace {_namespace}");
|
|
||||||
sb.AppendLine("{");
|
|
||||||
sb.AppendLine(" [Serializable]");
|
|
||||||
sb.AppendLine($" public class {className} : IId");
|
|
||||||
sb.AppendLine(" {");
|
|
||||||
|
|
||||||
List<string> types = new();
|
|
||||||
List<string> names = new();
|
|
||||||
List<string> tooltips = new();
|
|
||||||
|
|
||||||
foreach (var prop in sampleRow.Properties())
|
|
||||||
{
|
|
||||||
string rawName = prop.Name;
|
|
||||||
|
|
||||||
// 무시할 컬럼이면 continue
|
|
||||||
if (rawName.StartsWith("#")) continue;
|
|
||||||
|
|
||||||
string fieldName = rawName;
|
|
||||||
string explicitType = null;
|
|
||||||
|
|
||||||
if (rawName.Contains(":Enum"))
|
|
||||||
{
|
|
||||||
fieldName = rawName.Split(':')[0];
|
|
||||||
explicitType = fieldName;
|
|
||||||
}
|
|
||||||
else if (rawName.Contains(":") && rawName.EndsWith("_Enum"))
|
|
||||||
{
|
|
||||||
var parts = rawName.Split(':');
|
|
||||||
fieldName = parts[0];
|
|
||||||
explicitType = parts[1].Replace("_Enum", "");
|
|
||||||
}
|
|
||||||
else if (rawName.Contains(":NativeEnum"))
|
|
||||||
{
|
|
||||||
fieldName = rawName.Split(':')[0];
|
|
||||||
explicitType = fieldName;
|
|
||||||
}
|
|
||||||
else if (rawName.Contains(":"))
|
|
||||||
{
|
|
||||||
var parts = rawName.Split(':');
|
|
||||||
fieldName = parts[0];
|
|
||||||
explicitType = parts[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
types.Add(explicitType ?? GetCSharpType(prop.Value.Type));
|
|
||||||
names.Add(fieldName);
|
|
||||||
tooltips.Add(commentRow.TryGetValue(rawName, out var tip) ? tip.ToString() : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < names.Count; i++)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(tooltips[i]))
|
|
||||||
{
|
|
||||||
sb.AppendLine($" /// <summary>{tooltips[i]}</summary>");
|
|
||||||
sb.AppendLine($" [Tooltip(\"{tooltips[i]}\")]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (names[i] == "Id" && types[i] == "string")
|
|
||||||
{
|
|
||||||
sb.AppendLine(" [field: SerializeField]");
|
|
||||||
sb.AppendLine(" public string Id { get; set; }\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.AppendLine($" public {types[i]} {names[i]};\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.AppendLine(" }");
|
|
||||||
sb.AppendLine("}");
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetCSharpType(JTokenType jsonType)
|
|
||||||
{
|
|
||||||
switch (jsonType)
|
|
||||||
{
|
|
||||||
case JTokenType.Integer:
|
|
||||||
return "int";
|
|
||||||
case JTokenType.Float:
|
|
||||||
return "float";
|
|
||||||
case JTokenType.Boolean:
|
|
||||||
return "bool";
|
|
||||||
default:
|
|
||||||
return "string";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> CreateGoogleSheetSoAsync()
|
|
||||||
{
|
|
||||||
await Addressables.InitializeAsync().Task;
|
|
||||||
|
|
||||||
if (_isCreatingSo)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("[GoogleSheetManager] 이미 SO 생성 중입니다. 중복 호출 방지");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isCreatingSo = true;
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 🔁 카탈로그 업데이트 제거 (로컬 모드에서는 불필요)
|
|
||||||
Debug.Log("[GoogleSheetManager] 로컬 모드 - 카탈로그 업데이트 스킵");
|
|
||||||
|
|
||||||
result = InternalCreateGoogleSheetSoAsync();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[GoogleSheetManager] SO 생성 중 예외 발생: {e}");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_isCreatingSo = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result) // 성공적으로 SO 생성된 경우에만 빌드 수행
|
|
||||||
{
|
|
||||||
Debug.Log("[GoogleSheetManager] Addressables BuildPlayerContent 실행");
|
|
||||||
UnityEditor.AddressableAssets.Settings.AddressableAssetSettings.BuildPlayerContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<Type> GetAllTypesSafe()
|
|
||||||
{
|
|
||||||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
Type[] types;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
types = asm.GetTypes();
|
|
||||||
}
|
|
||||||
catch (ReflectionTypeLoadException ex)
|
|
||||||
{
|
|
||||||
types = ex.Types.Where(t => t != null).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var t in types)
|
|
||||||
if (t != null)
|
|
||||||
yield return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool InternalCreateGoogleSheetSoAsync()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_json))
|
|
||||||
{
|
|
||||||
Debug.LogError("[GoogleSheetManager] JSON 비어있음");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var root = JObject.Parse(_json);
|
|
||||||
bool allSuccess = true;
|
|
||||||
|
|
||||||
// 타입 캐시
|
|
||||||
var typeCache = GetAllTypesSafe()
|
|
||||||
.Where(t =>
|
|
||||||
t.IsClass &&
|
|
||||||
t.Namespace == _namespace &&
|
|
||||||
!t.Name.StartsWith("<") && // <>c 같은 컴파일러 생성 타입 제외
|
|
||||||
!Attribute.IsDefined(t, typeof(CompilerGeneratedAttribute))
|
|
||||||
)
|
|
||||||
.GroupBy(t => t.Name) // 같은 이름 여러 개면 첫 것만
|
|
||||||
.ToDictionary(g => g.Key, g => g.First());
|
|
||||||
|
|
||||||
string soDir = $"Assets{_generateFolderPath}/So";
|
|
||||||
if (!Directory.Exists(soDir))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(soDir);
|
|
||||||
AssetDatabase.ImportAsset(soDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var pair in root)
|
|
||||||
{
|
|
||||||
string sheet = pair.Key;
|
|
||||||
|
|
||||||
if (!IsSelected(sheet))
|
|
||||||
{
|
|
||||||
Debug.Log($"[GSM] Skip (not selected): {sheet}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
typeCache.TryGetValue(sheet, out var dataType);
|
|
||||||
typeCache.TryGetValue($"{sheet}So", out var soType);
|
|
||||||
|
|
||||||
if (dataType == null || soType == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[GSM] Type missing for '{sheet}'. ns='{_namespace}' " +
|
|
||||||
$"dataType={(dataType == null ? "null" : dataType.FullName)} " +
|
|
||||||
$"soType={(soType == null ? "null" : soType.FullName)}");
|
|
||||||
allSuccess = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
string soPath = $"{soDir}/{sheet}So.asset";
|
|
||||||
var so = AssetDatabase.LoadAssetAtPath<ScriptableObject>(soPath);
|
|
||||||
|
|
||||||
if (so == null)
|
|
||||||
{
|
|
||||||
Debug.Log($"[GSM] Creating SO asset: {soPath}");
|
|
||||||
so = ScriptableObject.CreateInstance(soType);
|
|
||||||
AssetDatabase.CreateAsset(so, soPath);
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
AssetDatabase.ImportAsset(soPath, ImportAssetOptions.ForceSynchronousImport);
|
|
||||||
|
|
||||||
// 존재 확인
|
|
||||||
var check = AssetDatabase.LoadAssetAtPath<ScriptableObject>(soPath);
|
|
||||||
Debug.Log(check ? $"[GSM] SO created OK: {soPath}" : $"[GSM] SO create FAILED: {soPath}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.Log($"[GSM] SO asset exists: {soPath}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 데이터 파싱 → 리스트
|
|
||||||
var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(dataType));
|
|
||||||
var rows = (JArray)pair.Value;
|
|
||||||
|
|
||||||
for (int i = 1; i < rows.Count; i++)
|
|
||||||
{
|
|
||||||
var row = (JObject)rows[i];
|
|
||||||
var inst = Activator.CreateInstance(dataType);
|
|
||||||
|
|
||||||
foreach (var prop in row.Properties())
|
|
||||||
{
|
|
||||||
var raw = prop.Name;
|
|
||||||
if (raw.StartsWith("#")) continue;
|
|
||||||
|
|
||||||
string field = raw.Contains(":") ? raw.Split(':')[0] : raw;
|
|
||||||
|
|
||||||
var f = dataType.GetField(field,
|
|
||||||
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
var p = dataType.GetProperty(field,
|
|
||||||
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
|
|
||||||
if (f == null && p == null) continue;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var target = f?.FieldType ?? p?.PropertyType;
|
|
||||||
object value;
|
|
||||||
|
|
||||||
if (target.IsEnum)
|
|
||||||
{
|
|
||||||
var k = NormalizeEnumKey(prop.Value.ToString());
|
|
||||||
value = Enum.TryParse(target, k, out var parsed)
|
|
||||||
? parsed
|
|
||||||
: Activator.CreateInstance(target);
|
|
||||||
}
|
|
||||||
else if (target == typeof(Color))
|
|
||||||
{
|
|
||||||
value = ColorUtility.TryParseHtmlString(prop.Value.ToString(), out var c) ? c : Color.white;
|
|
||||||
}
|
|
||||||
else if (target == typeof(string))
|
|
||||||
{
|
|
||||||
value = prop.Value.ToString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = Convert.ChangeType(prop.Value.ToString(), target);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f != null) f.SetValue(inst, value);
|
|
||||||
else if (p is { CanWrite: true }) p.SetValue(inst, value);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[{sheet}] 값 할당 실패 {raw} → {e.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetDataList 호출
|
|
||||||
var setMethod = soType.GetMethod("SetDataList",
|
|
||||||
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
if (setMethod == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"{soType.Name}에 SetDataList가 없습니다.");
|
|
||||||
allSuccess = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
setMethod.Invoke(so, new object[] { list });
|
|
||||||
EditorUtility.SetDirty(so);
|
|
||||||
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
AssetDatabase.Refresh();
|
|
||||||
|
|
||||||
// Addressables 자동 등록은 auto만 (팀별 환경오염 방지)
|
|
||||||
if (IsAuto(sheet))
|
|
||||||
GoogleSheetAddressableAutoSetup.AutoRegisterSo(soPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.Log("✅ SO 동기화 완료(선택 시트만, 변경 없어도 항상 반영)");
|
|
||||||
return allSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string NormalizeEnumKey(string input)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(input))
|
|
||||||
return "None";
|
|
||||||
|
|
||||||
// 특수문자 및 공백을 밑줄(_)로 치환
|
|
||||||
string validName = System.Text.RegularExpressions.Regex.Replace(input, @"[^a-zA-Z0-9_]+", "_");
|
|
||||||
|
|
||||||
// 숫자로 시작하는 경우 밑줄 추가
|
|
||||||
if (char.IsDigit(validName[0]))
|
|
||||||
validName = "_" + validName;
|
|
||||||
|
|
||||||
// 첫 글자 대문자화
|
|
||||||
return char.ToUpper(validName[0]) + validName.Substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnValidate()
|
|
||||||
{
|
|
||||||
if (_refreshTrigger && !_alreadyCreatedSo && EditorPrefs.GetBool("GoogleSheetManager_ShouldCreateSO"))
|
|
||||||
{
|
|
||||||
_refreshTrigger = false;
|
|
||||||
_alreadyCreatedSo = true;
|
|
||||||
|
|
||||||
EditorPrefs.SetBool("GoogleSheetManager_ShouldCreateSO", false); // 재실행 방지
|
|
||||||
|
|
||||||
EditorApplication.delayCall += () =>
|
|
||||||
{
|
|
||||||
_ = DelayAndCreateSo(); // 무시 가능한 비동기
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task DelayAndCreateSo()
|
|
||||||
{
|
|
||||||
await Task.Delay(300); // 300ms 지연 (너무 짧으면 반영 안됨)
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_json))
|
|
||||||
{
|
|
||||||
bool success = await CreateGoogleSheetSoAsync();
|
|
||||||
Debug.Log(success ? "Fetch done. SO 업데이트 완료" : "SO 생성 실패. 수동으로 Fetch를 다시 시도하세요.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task CreateSoAfterScriptReload()
|
|
||||||
{
|
|
||||||
if (_json != null)
|
|
||||||
{
|
|
||||||
Debug.Log("[GoogleSheetManager] Script Reload 이후 SO 생성 실행");
|
|
||||||
await CreateGoogleSheetSoAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.Callbacks;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public static class GoogleSheetPostProcessor
|
|
||||||
{
|
|
||||||
[DidReloadScripts]
|
|
||||||
private static void OnScriptsReloaded()
|
|
||||||
{
|
|
||||||
if (EditorPrefs.GetBool("GoogleSheetManager_ShouldCreateSO", false))
|
|
||||||
{
|
|
||||||
EditorPrefs.DeleteKey("GoogleSheetManager_ShouldCreateSO");
|
|
||||||
_ = GoogleSheetManager.Instance.CreateSoAfterScriptReload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: acef684d9f9959e4dbbf34cd1c9dfb37
|
|
@ -1,6 +1,7 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 99e82f09adb03584fba0e4366be017c9
|
guid: 7e514e02415867140926993a92bcf816
|
||||||
TextScriptImporter:
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 176b356799a34a2f9e9a212ebb8f586d
|
||||||
|
timeCreated: 1754925910
|
@ -0,0 +1,68 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.AddressableAssets;
|
||||||
|
using UnityEditor.AddressableAssets.Settings;
|
||||||
|
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class AddressablesRegistrar : IAddressablesRegistrar
|
||||||
|
{
|
||||||
|
private AddressableAssetSettings _settings;
|
||||||
|
private bool _dirty;
|
||||||
|
|
||||||
|
public AddressablesRegistrar()
|
||||||
|
{
|
||||||
|
_settings = AddressableAssetSettingsDefaultObject.Settings;
|
||||||
|
if (_settings == null)
|
||||||
|
Debug.LogError("[AddressablesRegistrar] Addressables Settings를 찾지 못했습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterOrMoveEntry(string assetPath, string groupName, string label, string addressOverride = null)
|
||||||
|
{
|
||||||
|
if (_settings == null) return;
|
||||||
|
|
||||||
|
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
||||||
|
if (string.IsNullOrEmpty(guid)) return;
|
||||||
|
|
||||||
|
var group = _settings.FindGroup(groupName);
|
||||||
|
if (group == null)
|
||||||
|
{
|
||||||
|
group = _settings.CreateGroup(groupName, false, false, false, null,
|
||||||
|
typeof(BundledAssetGroupSchema), typeof(ContentUpdateGroupSchema));
|
||||||
|
var bundled = group.GetSchema<BundledAssetGroupSchema>();
|
||||||
|
bundled.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackTogether;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entry = _settings.FindAssetEntry(guid);
|
||||||
|
if (entry == null) entry = _settings.CreateOrMoveEntry(guid, group);
|
||||||
|
else if (entry.parentGroup != group) _settings.MoveEntry(entry, group);
|
||||||
|
|
||||||
|
entry.address = string.IsNullOrEmpty(addressOverride)
|
||||||
|
? System.IO.Path.GetFileNameWithoutExtension(assetPath)
|
||||||
|
: addressOverride;
|
||||||
|
|
||||||
|
if (!entry.labels.Contains(label))
|
||||||
|
entry.SetLabel(label, true, true);
|
||||||
|
|
||||||
|
_settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, entry, true);
|
||||||
|
_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveAll()
|
||||||
|
{
|
||||||
|
if (!_dirty) return;
|
||||||
|
EditorUtility.SetDirty(_settings);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
_dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BuildIfNeeded(bool shouldBuild)
|
||||||
|
{
|
||||||
|
if (!shouldBuild || _settings == null) return;
|
||||||
|
AddressableAssetSettings.BuildPlayerContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 794fd8fb1485449f86dd73037cad2abc
|
||||||
|
timeCreated: 1754926004
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ae0646d42ada4352a2a089bda93fc49e
|
||||||
|
timeCreated: 1754925896
|
@ -0,0 +1,241 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class CSharpCodeGenerator : ICodeGenerator
|
||||||
|
{
|
||||||
|
private readonly ITypeNameResolver _resolver;
|
||||||
|
public CSharpCodeGenerator(ITypeNameResolver resolver) => _resolver = resolver;
|
||||||
|
|
||||||
|
public CodeGenerationResult Generate(string fullJson, IReadOnlyCollection<string> autoCreateSheets,
|
||||||
|
string rootNamespace, string generateAssetBasePath,
|
||||||
|
string enumTypesAssetPath, string classesFolderAssetPath)
|
||||||
|
{
|
||||||
|
var result = new CodeGenerationResult();
|
||||||
|
if (string.IsNullOrEmpty(fullJson)) return result;
|
||||||
|
|
||||||
|
JObject root;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
root = JObject.Parse(fullJson);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enum 후보 수집
|
||||||
|
var enumCandidates = new Dictionary<string, HashSet<string>>(StringComparer.Ordinal);
|
||||||
|
foreach (var pair in root)
|
||||||
|
{
|
||||||
|
if (!autoCreateSheets.Contains(pair.Key)) continue;
|
||||||
|
if (pair.Value is not JArray items || items.Count < 2) continue;
|
||||||
|
|
||||||
|
for (int i = 1; i < items.Count; i++)
|
||||||
|
{
|
||||||
|
foreach (var prop in ((JObject)items[i]).Properties())
|
||||||
|
{
|
||||||
|
var raw = prop.Name;
|
||||||
|
if (raw.StartsWith("#")) continue;
|
||||||
|
|
||||||
|
string enumType = null;
|
||||||
|
if (raw.Contains(":Enum")) enumType = raw.Split(':')[0];
|
||||||
|
else if (raw.Contains(":") && raw.EndsWith("_Enum"))
|
||||||
|
enumType = raw.Split(':')[1].Replace("_Enum", "");
|
||||||
|
else if (raw.Contains(":NativeEnum")) continue;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(enumType)) continue;
|
||||||
|
|
||||||
|
string enumValue = NormalizeEnumKey(prop.Value?.ToString() ?? "");
|
||||||
|
if (!enumCandidates.TryGetValue(enumType, out var set))
|
||||||
|
{
|
||||||
|
set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
enumCandidates.Add(enumType, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
set.Add(enumValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnumTypes.cs (결정성: 알파벳 정렬)
|
||||||
|
EnsureDirectory(enumTypesAssetPath);
|
||||||
|
File.WriteAllText(GoogleSheetSettingsSo.AssetToFull(enumTypesAssetPath),
|
||||||
|
BuildEnumCode(rootNamespace, enumCandidates));
|
||||||
|
AssetDatabase.ImportAsset(enumTypesAssetPath);
|
||||||
|
result.CreatedAssetPaths.Add(enumTypesAssetPath);
|
||||||
|
result.AnyFileCreated = true;
|
||||||
|
|
||||||
|
// Classes 폴더
|
||||||
|
if (!AssetDatabase.IsValidFolder(classesFolderAssetPath))
|
||||||
|
CreateFolderRecursive(classesFolderAssetPath);
|
||||||
|
|
||||||
|
foreach (var pair in root)
|
||||||
|
{
|
||||||
|
string className = pair.Key;
|
||||||
|
if (!autoCreateSheets.Contains(className)) continue;
|
||||||
|
if (pair.Value is not JArray items || items.Count < 2) continue;
|
||||||
|
|
||||||
|
string dataAssetPath = $"{classesFolderAssetPath}/{className}.cs";
|
||||||
|
string soAssetPath = $"{classesFolderAssetPath}/{className}So.cs";
|
||||||
|
|
||||||
|
if (!File.Exists(GoogleSheetSettingsSo.AssetToFull(dataAssetPath)))
|
||||||
|
{
|
||||||
|
EnsureDirectory(dataAssetPath);
|
||||||
|
File.WriteAllText(GoogleSheetSettingsSo.AssetToFull(dataAssetPath),
|
||||||
|
GenerateDataClass(rootNamespace, className, items));
|
||||||
|
AssetDatabase.ImportAsset(dataAssetPath);
|
||||||
|
result.CreatedAssetPaths.Add(dataAssetPath);
|
||||||
|
result.AnyFileCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(GoogleSheetSettingsSo.AssetToFull(soAssetPath)))
|
||||||
|
{
|
||||||
|
EnsureDirectory(soAssetPath);
|
||||||
|
File.WriteAllText(GoogleSheetSettingsSo.AssetToFull(soAssetPath),
|
||||||
|
GenerateSoClass(rootNamespace, className));
|
||||||
|
AssetDatabase.ImportAsset(soAssetPath);
|
||||||
|
result.CreatedAssetPaths.Add(soAssetPath);
|
||||||
|
result.AnyFileCreated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateFolderRecursive(string assetPath)
|
||||||
|
{
|
||||||
|
var parts = assetPath.Split('/');
|
||||||
|
string acc = parts[0]; // "Assets"
|
||||||
|
for (int i = 1; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
string next = $"{acc}/{parts[i]}";
|
||||||
|
if (!AssetDatabase.IsValidFolder(next))
|
||||||
|
AssetDatabase.CreateFolder(acc, parts[i]);
|
||||||
|
acc = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EnsureDirectory(string assetPath)
|
||||||
|
{
|
||||||
|
var full = GoogleSheetSettingsSo.AssetToFull(assetPath);
|
||||||
|
var dir = Path.GetDirectoryName(full);
|
||||||
|
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildEnumCode(string rootNamespace, Dictionary<string, HashSet<string>> enums)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("// <auto-generated>");
|
||||||
|
sb.AppendLine("using System;");
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine($"namespace {rootNamespace}");
|
||||||
|
sb.AppendLine("{");
|
||||||
|
|
||||||
|
foreach (var kv in enums.OrderBy(k => k.Key, StringComparer.Ordinal))
|
||||||
|
{
|
||||||
|
var enumName = IdentifierSanitizer.Sanitize(kv.Key, true);
|
||||||
|
var values = kv.Value
|
||||||
|
.Where(v => !string.IsNullOrWhiteSpace(v) &&
|
||||||
|
!string.Equals(v, "None", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.Select(v => IdentifierSanitizer.Sanitize(v, true))
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.OrderBy(v => v, StringComparer.Ordinal)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
sb.AppendLine($" public enum {enumName}");
|
||||||
|
sb.AppendLine(" {");
|
||||||
|
sb.AppendLine(" None = 0,");
|
||||||
|
for (int i = 0; i < values.Count; i++)
|
||||||
|
sb.AppendLine($" {values[i]} = {i + 1},");
|
||||||
|
sb.AppendLine(" }");
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine("}");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateSoClass(string rootNamespace, string className)
|
||||||
|
{
|
||||||
|
var safe = IdentifierSanitizer.Sanitize(className, true);
|
||||||
|
return
|
||||||
|
$@"// <auto-generated>
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace {rootNamespace}
|
||||||
|
{{
|
||||||
|
[CreateAssetMenu(fileName = ""{safe}So"", menuName = ""GoogleSheet/{safe}So"")]
|
||||||
|
public class {safe}So : DataSo<{safe}> {{ }}
|
||||||
|
}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateDataClass(string rootNamespace, string className, JArray items)
|
||||||
|
{
|
||||||
|
var commentRow = (JObject)items[0];
|
||||||
|
var sampleRow = (JObject)items[1];
|
||||||
|
|
||||||
|
var safeClass = IdentifierSanitizer.Sanitize(className, true);
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.AppendLine("// <auto-generated>");
|
||||||
|
sb.AppendLine("using System;");
|
||||||
|
sb.AppendLine("using UnityEngine;");
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine($"namespace {rootNamespace}");
|
||||||
|
sb.AppendLine("{");
|
||||||
|
sb.AppendLine(" [Serializable]");
|
||||||
|
sb.AppendLine($" public class {safeClass} : IId");
|
||||||
|
sb.AppendLine(" {");
|
||||||
|
|
||||||
|
foreach (var prop in sampleRow.Properties())
|
||||||
|
{
|
||||||
|
string rawHeader = prop.Name;
|
||||||
|
if (rawHeader.StartsWith("#")) continue;
|
||||||
|
|
||||||
|
string fieldName = rawHeader.Contains(":") ? rawHeader.Split(':')[0] : rawHeader;
|
||||||
|
fieldName = IdentifierSanitizer.Sanitize(fieldName, true);
|
||||||
|
|
||||||
|
string typeName = _resolver.ResolveFieldTypeName(rawHeader, prop.Value);
|
||||||
|
string tooltip = commentRow.TryGetValue(rawHeader, out var tip) ? tip.ToString() : "";
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(tooltip))
|
||||||
|
{
|
||||||
|
sb.AppendLine($" /// <summary>{tooltip}</summary>");
|
||||||
|
sb.AppendLine($" [Tooltip(\"{tooltip}\")]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldName == "Id" && typeName == "string")
|
||||||
|
{
|
||||||
|
sb.AppendLine(" [field: SerializeField]");
|
||||||
|
sb.AppendLine(" public string Id { get; set; }\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.AppendLine($" public {typeName} {fieldName};\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine(" }");
|
||||||
|
sb.AppendLine("}");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizeEnumKey(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input)) return "None";
|
||||||
|
var valid = System.Text.RegularExpressions.Regex.Replace(input, @"[^a-zA-Z0-9_]+", "_");
|
||||||
|
if (char.IsDigit(valid[0])) valid = "_" + valid;
|
||||||
|
return char.ToUpperInvariant(valid[0]) + valid.Substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9b30078a6640456ea2bda893f12b40e1
|
||||||
|
timeCreated: 1754925971
|
@ -0,0 +1,28 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class DefaultTypeNameResolver : ITypeNameResolver
|
||||||
|
{
|
||||||
|
public string ResolveFieldTypeName(string rawHeader, JToken sampleValue)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(rawHeader)) return "string";
|
||||||
|
|
||||||
|
if (rawHeader.Contains(":Enum")) return rawHeader.Split(':')[0];
|
||||||
|
if (rawHeader.Contains(":") && rawHeader.EndsWith("_Enum"))
|
||||||
|
return rawHeader.Split(':')[1].Replace("_Enum", "");
|
||||||
|
if (rawHeader.Contains(":NativeEnum")) return rawHeader.Split(':')[0];
|
||||||
|
if (rawHeader.Contains(":")) return rawHeader.Split(':')[1];
|
||||||
|
|
||||||
|
return sampleValue?.Type switch
|
||||||
|
{
|
||||||
|
JTokenType.Integer => "int",
|
||||||
|
JTokenType.Float => "float",
|
||||||
|
JTokenType.Boolean => "bool",
|
||||||
|
_ => "string"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 615215c08bd844f6a7a5625148b4df8a
|
||||||
|
timeCreated: 1754925977
|
@ -0,0 +1,25 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public static class IdentifierSanitizer
|
||||||
|
{
|
||||||
|
private static readonly HashSet<string> CSharpKeywords = new()
|
||||||
|
{
|
||||||
|
"class","struct","enum","namespace","public","private","protected","internal",
|
||||||
|
"static","void","int","float","double","decimal","string","bool",
|
||||||
|
"new","return","if","else","for","while","switch","case","default",
|
||||||
|
"break","continue","this","base","null","true","false","using"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static string Sanitize(string raw, bool pascalCase = false)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(raw)) return "_";
|
||||||
|
string s = System.Text.RegularExpressions.Regex.Replace(raw, @"[^\w]", "_");
|
||||||
|
if (char.IsDigit(s[0])) s = "_" + s;
|
||||||
|
if (pascalCase) s = char.ToUpperInvariant(s[0]) + s.Substring(1);
|
||||||
|
if (CSharpKeywords.Contains(s)) s = "_" + s;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 22119c040e354af5bbf8777f9430016b
|
||||||
|
timeCreated: 1754925982
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3f537f96e27749dd9d4ddfcdc0870ecc
|
||||||
|
timeCreated: 1754925901
|
@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using UnityEngine;
|
||||||
|
using Color = System.Drawing.Color;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class DefaultValueConverterRegistry : IValueConverterRegistry
|
||||||
|
{
|
||||||
|
public bool TryConvert(string source, Type targetType, out object value)
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
if (targetType == typeof(string)) { value = source ?? ""; return true; }
|
||||||
|
|
||||||
|
if (targetType == typeof(bool))
|
||||||
|
{
|
||||||
|
var s = (source ?? "").Trim();
|
||||||
|
if (bool.TryParse(s, out var b)) { value = b; return true; }
|
||||||
|
if (s == "1" || s.Equals("yes", StringComparison.OrdinalIgnoreCase)) { value = true; return true; }
|
||||||
|
if (s == "0" || s.Equals("no", StringComparison.OrdinalIgnoreCase)) { value = false; return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetType.IsEnum)
|
||||||
|
{
|
||||||
|
var key = NormalizeEnumKey(source);
|
||||||
|
if (Enum.TryParse(targetType, key, true, out var parsed)) { value = parsed; return true; }
|
||||||
|
value = Activator.CreateInstance(targetType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetType == typeof(int))
|
||||||
|
{
|
||||||
|
if (int.TryParse(source, NumberStyles.Integer, CultureInfo.InvariantCulture, out var i)) { value = i; return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (targetType == typeof(float))
|
||||||
|
{
|
||||||
|
if (float.TryParse(source, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var f)) { value = f; return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (targetType == typeof(double))
|
||||||
|
{
|
||||||
|
if (double.TryParse(source, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var d)) { value = d; return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (targetType == typeof(decimal))
|
||||||
|
{
|
||||||
|
if (decimal.TryParse(source, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var m)) { value = m; return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetType == typeof(Color))
|
||||||
|
{
|
||||||
|
if (ColorUtility.TryParseHtmlString(source, out var c)) { value = c; return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
value = Convert.ChangeType(source, targetType, CultureInfo.InvariantCulture);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizeEnumKey(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input)) return "None";
|
||||||
|
string valid = System.Text.RegularExpressions.Regex.Replace(input, @"[^a-zA-Z0-9_]+", "_");
|
||||||
|
if (char.IsDigit(valid[0])) valid = "_" + valid;
|
||||||
|
return char.ToUpperInvariant(valid[0]) + valid.Substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 38fb58c2a107435997dc9dfef500a644
|
||||||
|
timeCreated: 1754925991
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3e17817ee69f4a3eb23ba2132644e157
|
||||||
|
timeCreated: 1754925891
|
@ -0,0 +1,68 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public class GoogleSheetDiffViewer : EditorWindow
|
||||||
|
{
|
||||||
|
private List<GoogleSheetDiff> _diffs;
|
||||||
|
private bool _isReversed;
|
||||||
|
private Vector2 _scroll;
|
||||||
|
|
||||||
|
public static void ShowWindow(List<GoogleSheetDiff> diffs, bool isReversed = false)
|
||||||
|
{
|
||||||
|
var window = GetWindow<GoogleSheetDiffViewer>("Google Sheet 변경점");
|
||||||
|
window._diffs = diffs;
|
||||||
|
window._isReversed = isReversed;
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField("변경된 항목", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.Space();
|
||||||
|
|
||||||
|
if (_diffs == null || _diffs.Count == 0)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("변경 사항이 없습니다.", MessageType.Info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.BeginHorizontal("box");
|
||||||
|
EditorGUILayout.LabelField("시트", EditorStyles.boldLabel, GUILayout.Width(80));
|
||||||
|
EditorGUILayout.LabelField("행", EditorStyles.boldLabel, GUILayout.Width(40));
|
||||||
|
EditorGUILayout.LabelField("필드", EditorStyles.boldLabel, GUILayout.Width(140));
|
||||||
|
|
||||||
|
GUIStyle oldStyle = new GUIStyle(EditorStyles.label) { normal = { textColor = Color.green } };
|
||||||
|
EditorGUILayout.LabelField(_isReversed ? "현재 버전" : "변경 전", oldStyle, GUILayout.Width(100));
|
||||||
|
|
||||||
|
GUIStyle newStyle = new GUIStyle(EditorStyles.label) { normal = { textColor = new Color(0.3f, 0.75f, 1.0f) } };
|
||||||
|
EditorGUILayout.LabelField(_isReversed ? "선택한 버전" : "변경 후", newStyle, GUILayout.Width(100));
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
_scroll = EditorGUILayout.BeginScrollView(_scroll);
|
||||||
|
|
||||||
|
foreach (var diff in _diffs)
|
||||||
|
{
|
||||||
|
EditorGUILayout.BeginHorizontal("box");
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField(diff.Sheet, GUILayout.Width(80));
|
||||||
|
EditorGUILayout.LabelField(diff.RowIndex.ToString(), GUILayout.Width(40));
|
||||||
|
EditorGUILayout.LabelField(diff.Field, GUILayout.Width(140));
|
||||||
|
|
||||||
|
string left = _isReversed ? diff.NewValue : diff.OldValue;
|
||||||
|
string right = _isReversed ? diff.OldValue : diff.NewValue;
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField(left, oldStyle, GUILayout.Width(100));
|
||||||
|
EditorGUILayout.LabelField(right, newStyle, GUILayout.Width(100));
|
||||||
|
|
||||||
|
EditorGUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,60 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class NewtonsoftJsonDiffer : IJsonDiffer
|
||||||
|
{
|
||||||
|
public List<GoogleSheetDiff> Compare(string oldJson, string newJson)
|
||||||
|
{
|
||||||
|
var diffs = new List<GoogleSheetDiff>();
|
||||||
|
if (string.IsNullOrEmpty(oldJson) || string.IsNullOrEmpty(newJson)) return diffs;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var oldObj = JObject.Parse(oldJson);
|
||||||
|
var newObj = JObject.Parse(newJson);
|
||||||
|
|
||||||
|
foreach (var sheet in newObj)
|
||||||
|
{
|
||||||
|
if (!oldObj.TryGetValue(sheet.Key, out var oldSheetToken)) continue;
|
||||||
|
var newArr = sheet.Value as JArray;
|
||||||
|
var oldArr = oldSheetToken as JArray;
|
||||||
|
if (newArr == null || oldArr == null) continue;
|
||||||
|
|
||||||
|
int min = Mathf.Min(newArr.Count, oldArr.Count);
|
||||||
|
for (int i = 1; i < min; i++)
|
||||||
|
{
|
||||||
|
var newRow = (JObject)newArr[i];
|
||||||
|
var oldRow = (JObject)oldArr[i];
|
||||||
|
|
||||||
|
foreach (var prop in newRow.Properties())
|
||||||
|
{
|
||||||
|
string n = prop.Value?.ToString() ?? "";
|
||||||
|
string o = oldRow.TryGetValue(prop.Name, out var ov) ? ov?.ToString() ?? "" : "";
|
||||||
|
if (n != o)
|
||||||
|
{
|
||||||
|
diffs.Add(new GoogleSheetDiff
|
||||||
|
{
|
||||||
|
Sheet = sheet.Key,
|
||||||
|
Field = prop.Name,
|
||||||
|
RowIndex = i,
|
||||||
|
OldValue = o,
|
||||||
|
NewValue = n
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
return diffs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7046da15bf734ab49bcada6844f87ade
|
||||||
|
timeCreated: 1754925964
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d2dec2cbe46d49d5aee5c5438d4da327
|
||||||
|
timeCreated: 1754925917
|
@ -0,0 +1,95 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Callbacks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class SessionStateReloadCoordinator : IReloadCoordinator
|
||||||
|
{
|
||||||
|
private const string KeyShouldRun = "DDD_GSM_ShouldRun";
|
||||||
|
private const string KeyManagerPath = "DDD_GSM_ManagerPath";
|
||||||
|
|
||||||
|
public void RequestPostCompileSoSync(GoogleSheetManager manager)
|
||||||
|
{
|
||||||
|
var path = AssetDatabase.GetAssetPath(manager);
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[ReloadCoordinator] GoogleSheetManager 경로를 찾을 수 없습니다.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 리로드 후 이어서 실행하라는 플래그 + 매니저 경로 저장
|
||||||
|
SessionState.SetBool(KeyShouldRun, true);
|
||||||
|
SessionState.SetString(KeyManagerPath, path);
|
||||||
|
|
||||||
|
// 혹시 이미 컴파일이 끝나 있었다면 바로 한 번 더 체크
|
||||||
|
EditorApplication.delayCall += TryRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 에디터가 켜질 때도, 리로드 직후도 여기로 들어오게 한다
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void InitOnLoad() => EditorApplication.delayCall += TryRun;
|
||||||
|
|
||||||
|
[DidReloadScripts]
|
||||||
|
private static void OnScriptsReloaded() => EditorApplication.delayCall += TryRun;
|
||||||
|
|
||||||
|
private static async void TryRun()
|
||||||
|
{
|
||||||
|
if (!SessionState.GetBool(KeyShouldRun, false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 아직 컴파일 중이면 다음 프레임에 재시도
|
||||||
|
if (EditorApplication.isCompiling)
|
||||||
|
{
|
||||||
|
EditorApplication.delayCall += TryRun;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 플래그 회수
|
||||||
|
SessionState.EraseBool(KeyShouldRun);
|
||||||
|
|
||||||
|
// 매니저 에셋 로드
|
||||||
|
var path = SessionState.GetString(KeyManagerPath, "");
|
||||||
|
SessionState.EraseString(KeyManagerPath);
|
||||||
|
|
||||||
|
GoogleSheetManager manager = null;
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
manager = AssetDatabase.LoadAssetAtPath<GoogleSheetManager>(path);
|
||||||
|
|
||||||
|
if (manager == null)
|
||||||
|
{
|
||||||
|
// 경로 저장이 실패했을 경우 타입으로 검색(폴백)
|
||||||
|
var guid = AssetDatabase.FindAssets("t:GoogleSheetManager").FirstOrDefault();
|
||||||
|
if (!string.IsNullOrEmpty(guid))
|
||||||
|
{
|
||||||
|
var p = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
|
manager = AssetDatabase.LoadAssetAtPath<GoogleSheetManager>(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("[ReloadCoordinator] GoogleSheetManager 에셋을 찾지 못했습니다.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 리로드 후 후속 SO 동기화 실행
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 짧은 안정화 대기 (도메인 리로드 직후 임포트 마무리용)
|
||||||
|
await Task.Delay(100);
|
||||||
|
await manager.ContinueSoSyncAfterReload_Public(); // ← 아래 3) 참고(퍼블릭 메서드)
|
||||||
|
}
|
||||||
|
catch (System.Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[ReloadCoordinator] 후속 실행 중 예외: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 06e205705bf641e9bef9d0ffd54ff2a6
|
||||||
|
timeCreated: 1754926015
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 154be435047b48c09ff4301ceba2057d
|
||||||
|
timeCreated: 1754925883
|
@ -0,0 +1,29 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class LocalAssetJsonSource : IGoogleSheetSource
|
||||||
|
{
|
||||||
|
private readonly GoogleSheetSettingsSo _settings;
|
||||||
|
public LocalAssetJsonSource(GoogleSheetSettingsSo settings) => _settings = settings;
|
||||||
|
|
||||||
|
public Task<string> FetchAllJsonAsync()
|
||||||
|
{
|
||||||
|
// 프로젝트 내부 AssetPath의 작업 JSON을 읽음
|
||||||
|
var text = AssetDatabase.LoadAssetAtPath<TextAsset>(_settings.JsonWorkFileAssetPath);
|
||||||
|
if (text != null) return Task.FromResult(text.text);
|
||||||
|
|
||||||
|
// 파일이 TextAsset으로 임포트되지 않았다면 파일로 읽기
|
||||||
|
var full = GoogleSheetSettingsSo.AssetToFull(_settings.JsonWorkFileAssetPath);
|
||||||
|
if (File.Exists(full)) return Task.FromResult(File.ReadAllText(full));
|
||||||
|
|
||||||
|
Debug.LogWarning($"[LocalAssetJsonSource] 작업 JSON이 없습니다: {_settings.JsonWorkFileAssetPath}");
|
||||||
|
return Task.FromResult<string>(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d1cc71a02cce46dcbe05b15dc211448d
|
||||||
|
timeCreated: 1754925958
|
@ -0,0 +1,50 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class WebAppGoogleSheetSource : IGoogleSheetSource
|
||||||
|
{
|
||||||
|
private readonly GoogleSheetSettingsSo _settings;
|
||||||
|
public WebAppGoogleSheetSource(GoogleSheetSettingsSo settings) => _settings = settings;
|
||||||
|
|
||||||
|
public async Task<string> FetchAllJsonAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(_settings.WebAppUrl))
|
||||||
|
{
|
||||||
|
Debug.LogError("[WebAppGoogleSheetSource] WebAppUrl 비어있음");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var handler = new HttpClientHandler { UseProxy = _settings.UseSystemProxy };
|
||||||
|
using var client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(_settings.HttpTimeoutSeconds) };
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var resp = await client.GetAsync(_settings.WebAppUrl, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||||
|
resp.EnsureSuccessStatusCode();
|
||||||
|
var json = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
// 작업용 JSON을 AssetPath에 저장해 팀과 공유
|
||||||
|
var fullPath = GoogleSheetSettingsSo.AssetToFull(_settings.JsonWorkFileAssetPath);
|
||||||
|
var dir = Path.GetDirectoryName(fullPath);
|
||||||
|
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir);
|
||||||
|
File.WriteAllText(fullPath, json);
|
||||||
|
// AssetDatabase.ImportAsset(_settings.JsonWorkFileAssetPath);
|
||||||
|
Debug.Log($"[WebAppGoogleSheetSource] Fetch OK, length={json?.Length ?? 0}");
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError($"[WebAppGoogleSheetSource] 오류: {e}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ca5370e3b0114cdd9d7a5db8f4f709c7
|
||||||
|
timeCreated: 1754925953
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 457c112c40574497804a44bee76d29dd
|
||||||
|
timeCreated: 1754925906
|
@ -0,0 +1,150 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class SoSynchronizer : ISoSynchronizer
|
||||||
|
{
|
||||||
|
private readonly IValueConverterRegistry _converter;
|
||||||
|
private readonly List<string> _updatedPaths = new();
|
||||||
|
public IReadOnlyList<string> UpdatedSoAssetPaths => _updatedPaths;
|
||||||
|
|
||||||
|
public SoSynchronizer(IValueConverterRegistry converter) => _converter = converter;
|
||||||
|
|
||||||
|
public bool SynchronizeAll(string fullJson, IReadOnlyCollection<string> selectedSheets, string rootNamespace, string soFolderAssetPath)
|
||||||
|
{
|
||||||
|
_updatedPaths.Clear();
|
||||||
|
if (string.IsNullOrEmpty(fullJson)) return false;
|
||||||
|
|
||||||
|
var root = JObject.Parse(fullJson);
|
||||||
|
bool allSuccess = true;
|
||||||
|
|
||||||
|
// 폴더 보장
|
||||||
|
if (!AssetDatabase.IsValidFolder(soFolderAssetPath))
|
||||||
|
CreateFolderRecursive(soFolderAssetPath);
|
||||||
|
|
||||||
|
// 타입 캐시
|
||||||
|
var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.SelectMany(a => {
|
||||||
|
try { return a.GetTypes(); }
|
||||||
|
catch (ReflectionTypeLoadException ex) { return ex.Types.Where(t => t != null); }
|
||||||
|
})
|
||||||
|
.Where(t => t != null && t.IsClass && t.Namespace == rootNamespace && !t.Name.StartsWith("<"))
|
||||||
|
.GroupBy(t => t.Name)
|
||||||
|
.ToDictionary(g => g.Key, g => g.First());
|
||||||
|
|
||||||
|
Debug.Log($"[SoSync] soFolder={soFolderAssetPath}");
|
||||||
|
Debug.Log($"[SoSync] selected: {string.Join(", ", selectedSheets)}");
|
||||||
|
|
||||||
|
foreach (var pair in root)
|
||||||
|
{
|
||||||
|
string sheet = pair.Key;
|
||||||
|
if (!selectedSheets.Contains(sheet))
|
||||||
|
{
|
||||||
|
Debug.Log($"[SoSync] SKIP(not selected): {sheet}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
types.TryGetValue(sheet, out var dataType);
|
||||||
|
types.TryGetValue($"{sheet}So", out var soType);
|
||||||
|
if (dataType == null || soType == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[SoSynchronizer] 타입 누락: {sheet} (data={dataType}, so={soType})");
|
||||||
|
allSuccess = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string soAssetPath = $"{soFolderAssetPath}/{sheet}So.asset";
|
||||||
|
var so = AssetDatabase.LoadAssetAtPath<ScriptableObject>(soAssetPath);
|
||||||
|
if (so == null)
|
||||||
|
{
|
||||||
|
Debug.Log($"[SoSync] CREATE SO: {soAssetPath}");
|
||||||
|
so = ScriptableObject.CreateInstance(soType);
|
||||||
|
AssetDatabase.CreateAsset(so, soAssetPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log($"[SoSync] FOUND SO: {soAssetPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(dataType));
|
||||||
|
var rows = (JArray)pair.Value;
|
||||||
|
|
||||||
|
for (int i = 1; i < rows.Count; i++)
|
||||||
|
{
|
||||||
|
var row = (JObject)rows[i];
|
||||||
|
var inst = Activator.CreateInstance(dataType);
|
||||||
|
|
||||||
|
foreach (var prop in row.Properties())
|
||||||
|
{
|
||||||
|
var raw = prop.Name;
|
||||||
|
if (raw.StartsWith("#")) continue;
|
||||||
|
|
||||||
|
string field = raw.Contains(":") ? raw.Split(':')[0] : raw;
|
||||||
|
var f = dataType.GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
var p = dataType.GetProperty(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
if (f == null && p == null) continue;
|
||||||
|
|
||||||
|
var targetType = f?.FieldType ?? p?.PropertyType;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_converter.TryConvert(prop.Value?.ToString(), targetType, out var converted))
|
||||||
|
{
|
||||||
|
if (f != null) f.SetValue(inst, converted);
|
||||||
|
else if (p is { CanWrite: true }) p.SetValue(inst, converted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[SoSynchronizer] 변환 실패: {sheet}.{field} -> {targetType?.Name} (원본:'{prop.Value}')");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[SoSynchronizer] 값 할당 예외: {sheet}.{field} -> {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
var setMethod = soType.GetMethod("SetDataList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
if (setMethod == null)
|
||||||
|
{
|
||||||
|
Debug.LogError($"{soType.Name}에 SetDataList 메서드가 없습니다.");
|
||||||
|
allSuccess = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Debug.Log($"[SoSync] INVOKE SetDataList for {sheet} (rows={(pair.Value as JArray)?.Count ?? 0})");
|
||||||
|
|
||||||
|
setMethod.Invoke(so, new object[] { list });
|
||||||
|
EditorUtility.SetDirty(so);
|
||||||
|
_updatedPaths.Add(soAssetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
return allSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CreateFolderRecursive(string assetPath)
|
||||||
|
{
|
||||||
|
var parts = assetPath.Split('/');
|
||||||
|
string acc = parts[0]; // Assets
|
||||||
|
for (int i = 1; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
string next = $"{acc}/{parts[i]}";
|
||||||
|
if (!AssetDatabase.IsValidFolder(next))
|
||||||
|
AssetDatabase.CreateFolder(acc, parts[i]);
|
||||||
|
acc = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6a55e8e97a9a4549b980ba97cef9e45c
|
||||||
|
timeCreated: 1754925998
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8779f010104a4df5a30a7d75261b9b1c
|
||||||
|
timeCreated: 1754925914
|
@ -0,0 +1,92 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System.IO;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class GoogleSheetChangeLogVersionStore : IVersionStore
|
||||||
|
{
|
||||||
|
private readonly string _changeLogAssetPath;
|
||||||
|
public GoogleSheetChangeLogVersionStore(string changeLogAssetPath) => _changeLogAssetPath = changeLogAssetPath;
|
||||||
|
|
||||||
|
public string GetLatestJsonOrEmpty()
|
||||||
|
{
|
||||||
|
var log = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(_changeLogAssetPath);
|
||||||
|
if (log == null || log.Logs.Count == 0) return "";
|
||||||
|
return log.Logs[^1].JsonSnapshot ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveSnapshot(string json, string editorName, string backupsFolderAssetPath)
|
||||||
|
{
|
||||||
|
// 1) 체인지로그 에셋이 없으면 폴더부터 보장
|
||||||
|
var dir = Path.GetDirectoryName(_changeLogAssetPath)?.Replace("\\", "/");
|
||||||
|
EnsureAssetFolder(dir);
|
||||||
|
|
||||||
|
var log = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(_changeLogAssetPath);
|
||||||
|
if (log == null)
|
||||||
|
{
|
||||||
|
log = ScriptableObject.CreateInstance<GoogleSheetChangeLog>();
|
||||||
|
AssetDatabase.CreateAsset(log, _changeLogAssetPath);
|
||||||
|
AssetDatabase.ImportAsset(_changeLogAssetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) 로그 추가
|
||||||
|
string timestamp = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
log.AddEntry(new GoogleSheetChangeLog.LogEntry { Editor = editorName, Timestamp = timestamp, JsonSnapshot = json });
|
||||||
|
|
||||||
|
EditorUtility.SetDirty(log);
|
||||||
|
AssetDatabase.SaveAssets();
|
||||||
|
|
||||||
|
// 3) 백업 파일도 AssetPath 하위에 생성 (폴더 보장 + 임포트)
|
||||||
|
if (!string.IsNullOrEmpty(backupsFolderAssetPath))
|
||||||
|
{
|
||||||
|
EnsureAssetFolder(backupsFolderAssetPath);
|
||||||
|
string safe = timestamp.Replace(":", "-");
|
||||||
|
string fileAssetPath = $"{backupsFolderAssetPath}/{safe} by {editorName}.json";
|
||||||
|
|
||||||
|
File.WriteAllText(GoogleSheetSettingsSo.AssetToFull(fileAssetPath), json);
|
||||||
|
AssetDatabase.ImportAsset(fileAssetPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetSnapshotAt(int index)
|
||||||
|
{
|
||||||
|
var log = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(_changeLogAssetPath);
|
||||||
|
if (log == null) return "";
|
||||||
|
if (index < 0 || index >= log.Logs.Count) return "";
|
||||||
|
return log.Logs[index].JsonSnapshot ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int SnapshotCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var log = AssetDatabase.LoadAssetAtPath<GoogleSheetChangeLog>(_changeLogAssetPath);
|
||||||
|
return log == null ? 0 : log.Logs.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 중요한 보조 함수: AssetPath 폴더 보장 (슬래시 정규화 + 단계별 생성)
|
||||||
|
private static void EnsureAssetFolder(string assetDir)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(assetDir)) return;
|
||||||
|
var path = assetDir.Replace("\\", "/").TrimEnd('/');
|
||||||
|
if (AssetDatabase.IsValidFolder(path)) return;
|
||||||
|
|
||||||
|
var parts = path.Split('/');
|
||||||
|
if (parts.Length == 0 || parts[0] != "Assets")
|
||||||
|
throw new System.Exception($"Asset path must start with 'Assets/': {path}");
|
||||||
|
|
||||||
|
string acc = "Assets";
|
||||||
|
for (int i = 1; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
string next = $"{acc}/{parts[i]}";
|
||||||
|
if (!AssetDatabase.IsValidFolder(next))
|
||||||
|
AssetDatabase.CreateFolder(acc, parts[i]);
|
||||||
|
acc = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7fed1695995346aab1abdf8c8e7c0399
|
||||||
|
timeCreated: 1754926010
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 397392f2c0f514f4ca13c51c0af8e2f0
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public interface IAddressablesRegistrar
|
||||||
|
{
|
||||||
|
void RegisterOrMoveEntry(string assetPath, string groupName, string label, string addressOverride = null);
|
||||||
|
void SaveAll();
|
||||||
|
void BuildIfNeeded(bool shouldBuild);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4965067595f849f8b9a5c0083a181de9
|
||||||
|
timeCreated: 1754925853
|
@ -0,0 +1,16 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public sealed class CodeGenerationResult
|
||||||
|
{
|
||||||
|
public bool AnyFileCreated;
|
||||||
|
public List<string> CreatedAssetPaths = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICodeGenerator
|
||||||
|
{
|
||||||
|
CodeGenerationResult Generate(string fullJson, IReadOnlyCollection<string> autoCreateSheets, string rootNamespace, string generateAssetBasePath,
|
||||||
|
string enumTypesAssetPath, string classesFolderAssetPath);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2c57d237cbac4907b4f1e1b9047019f5
|
||||||
|
timeCreated: 1754925825
|
@ -0,0 +1,9 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DDD
|
||||||
|
{
|
||||||
|
public interface IGoogleSheetSource
|
||||||
|
{
|
||||||
|
Task<string> FetchAllJsonAsync(); // WebApp에서 가져오거나, AssetPath의 작업 JSON을 읽음
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e5d6c83a531f4017adac059edef2e9cb
|
||||||
|
timeCreated: 1754925804
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user