You need to sign in or sign up before continuing.
Commit 29f844aa authored by Senator John's avatar Senator John 💬

Merge branch 'patch' into 'master'

Patch

See merge request !28
parents 2a369a96 08a8d2c2
...@@ -346,6 +346,10 @@ MonoBehaviour: ...@@ -346,6 +346,10 @@ MonoBehaviour:
listOpRemoved: {fileID: 21300000, guid: 066065a6b1b767c418d2889597305402, type: 3} listOpRemoved: {fileID: 21300000, guid: 066065a6b1b767c418d2889597305402, type: 3}
listMyXyz: {fileID: 21300000, guid: dcbfe2b5c52ef9c45a945e6099f96860, type: 3} listMyXyz: {fileID: 21300000, guid: dcbfe2b5c52ef9c45a945e6099f96860, type: 3}
listOpXyz: {fileID: 21300000, guid: dc626d3f4895db448969ee261eac22c6, type: 3} listOpXyz: {fileID: 21300000, guid: dc626d3f4895db448969ee261eac22c6, type: 3}
listSingleColumn: {fileID: 21300000, guid: 1593fc89217af42499c6ab1514ab1709, type: 3}
listViewIconExpand: {fileID: 21300000, guid: 838190b6b8c45334bab89da28a238150, type: 3}
listViewIconDefault: {fileID: 21300000, guid: 9f9e97c267d35b84db512595c857ffba, type: 3}
listCardStatsBase: {fileID: 21300000, guid: 5b696a850bf3a3443bf0e67396ecc181, type: 3}
CardAffectDisable: {fileID: 21300000, guid: 5e4f5281aaf73274c888adbe5afce0e0, type: 3} CardAffectDisable: {fileID: 21300000, guid: 5e4f5281aaf73274c888adbe5afce0e0, type: 3}
CardAffectEquip: {fileID: 21300000, guid: 1a678cbbdf93a5449aa105d7c2d6d83a, type: 3} CardAffectEquip: {fileID: 21300000, guid: 1a678cbbdf93a5449aa105d7c2d6d83a, type: 3}
CardAffectField: {fileID: 21300000, guid: 4185642e1b53a404ea1e358e5ccda6fe, type: 3} CardAffectField: {fileID: 21300000, guid: 4185642e1b53a404ea1e358e5ccda6fe, type: 3}
......
...@@ -99,6 +99,9 @@ namespace MDPro3.Duel ...@@ -99,6 +99,9 @@ namespace MDPro3.Duel
UIManager.UIBlackIn(Core.TransitionTime); UIManager.UIBlackIn(Core.TransitionTime);
await UniTask.WaitForSeconds(Core.TransitionTime); await UniTask.WaitForSeconds(Core.TransitionTime);
await UniTask.WaitUntil(() => Appearance.loaded); await UniTask.WaitUntil(() => Appearance.loaded);
// Rebuild appearance assets on each match load so random selections
// (icon / frame / protector) are re-rolled per duel.
await Program.instance.appearance.LoadSettingAssets();
await ABLoader.CacheMasterDuelBundles(); await ABLoader.CacheMasterDuelBundles();
Program.instance.ocgcore.LoadDuelButton(); Program.instance.ocgcore.LoadDuelButton();
......
...@@ -255,7 +255,7 @@ namespace MDPro3 ...@@ -255,7 +255,7 @@ namespace MDPro3
manager.GetElement("PropertyMonster").SetActive(false); manager.GetElement("PropertyMonster").SetActive(false);
manager.GetElement("PropertySpell").SetActive(true); manager.GetElement("PropertySpell").SetActive(true);
manager.GetElement<Image>("SpellType").sprite = TextureManager.GetSpellTrapTypeIcon(data); manager.GetElement<Image>("SpellType").sprite = TextureManager.GetSpellTrapTypeIcon(data);
manager.GetElement<Text>("TextSpellType").text = data.GetSpellTrapType(); manager.GetElement<Text>("TextSpellType").text = data.GetSpellTrapType(true);
} }
RefreshLimitIcon(data.Id); RefreshLimitIcon(data.Id);
} }
......
...@@ -10,6 +10,31 @@ namespace MDPro3.UI ...@@ -10,6 +10,31 @@ namespace MDPro3.UI
{ {
public class CardList : MonoBehaviour public class CardList : MonoBehaviour
{ {
const float SingleColumnItemStep = 140f;
const int ExtraDeckColumns = 3;
const float ExtraDeckBaseItemWidth = 78f;
const float ExtraDeckVisualItemHeight = 124f;
const float ExtraDeckScrollbarWidth = 20f;
const float ExtraDeckHorizontalInset = 10f;
const float ExtraDeckHorizontalGap = 16f;
const float ExtraDeckVerticalGap = 20f;
const float ExtraDeckRowLineHeight = 2f;
const float ExtraDeckToggleButtonWidth = 64f;
const float ExtraDeckToggleButtonHeight = 62f;
const float ExtraDeckToggleButtonIconSize = 42f;
const float ExtraDeckToggleButtonOverlap = 0f;
const float ExtraDeckToggleButtonTopInset = 0f;
const float ExtraDeckToggleAdornmentWidth = 40f;
const float ExtraDeckToggleAdornmentHeight = 106f;
const float ExtraDeckToggleAdornmentVisibleStartX = 22f;
const float ExtraDeckToggleAdornmentOffsetY = 22f;
const float ExtraDeckToggleJoinPatchWidth = 16f;
const float ExtraDeckToggleJoinPatchHeight = 16f;
const float ExtraDeckToggleJoinPatchOffsetX = ExtraDeckToggleButtonWidth - 2f;
const float ExtraDeckToggleJoinPatchOffsetY = 0f;
const float ExtraDeckToggleJoinPatchTopLineHeight = 2f;
const float HiddenPadding = 20f;
public RectTransform baseRect; public RectTransform baseRect;
public Image locationIcon; public Image locationIcon;
public ScrollRect scrollRect; public ScrollRect scrollRect;
...@@ -23,6 +48,14 @@ namespace MDPro3.UI ...@@ -23,6 +48,14 @@ namespace MDPro3.UI
CardLocation location; CardLocation location;
int controller; int controller;
bool showWithCloseDuelLog = false; bool showWithCloseDuelLog = false;
float defaultBaseWidth = -1f;
bool extraDeckGridMode = false;
Button extraDeckModeButton;
Image extraDeckModeButtonIcon;
RectTransform extraDeckModeButtonSeamRect;
RectTransform extraDeckModeButtonJoinPatchRect;
RectTransform extraDeckModeButtonJoinPatchTopLineRect;
public void Show(List<GameCard> cards, CardLocation location, int controller) public void Show(List<GameCard> cards, CardLocation location, int controller)
{ {
if(OcgCore.cantCheckGrave && location == CardLocation.Grave) if(OcgCore.cantCheckGrave && location == CardLocation.Grave)
...@@ -31,9 +64,12 @@ namespace MDPro3.UI ...@@ -31,9 +64,12 @@ namespace MDPro3.UI
return; return;
} }
var previousLocation = this.location;
this.cards = cards; this.cards = cards;
this.location = location; this.location = location;
this.controller = controller; this.controller = controller;
if (IsToggleListLocation(this.location) && (!showing || !IsToggleListLocation(previousLocation)))
extraDeckGridMode = false;
if (!showing) if (!showing)
{ {
...@@ -48,7 +84,7 @@ namespace MDPro3.UI ...@@ -48,7 +84,7 @@ namespace MDPro3.UI
} }
else else
{ {
baseRect.DOAnchorPosX(150, transitionTime).OnComplete(() => baseRect.DOAnchorPosX(GetHiddenPosX(), transitionTime).OnComplete(() =>
{ {
RefreshList(); RefreshList();
baseRect.DOAnchorPosX(-30, transitionTime);// TODO: tween in tween baseRect.DOAnchorPosX(-30, transitionTime);// TODO: tween in tween
...@@ -64,7 +100,9 @@ namespace MDPro3.UI ...@@ -64,7 +100,9 @@ namespace MDPro3.UI
if (!showing) if (!showing)
return; return;
showing = false; showing = false;
baseRect.DOAnchorPosX(150f * Config.GetUIScale(1.18f) + SafeAreaAdapter.GetSafeAreaRightOffset(), 0.3f); if (extraDeckModeButton != null)
extraDeckModeButton.gameObject.SetActive(false);
baseRect.DOAnchorPosX(GetHiddenPosX(), 0.3f);
if(showWithCloseDuelLog) if(showWithCloseDuelLog)
{ {
showWithCloseDuelLog = false; showWithCloseDuelLog = false;
...@@ -74,21 +112,446 @@ namespace MDPro3.UI ...@@ -74,21 +112,446 @@ namespace MDPro3.UI
void RefreshList() void RefreshList()
{ {
EnsureWidthForLocation();
EnsureExtraDeckModeToggle();
UpdateExtraDeckModeToggle();
locationIcon.sprite = GetListLocationIcon(location, controller); locationIcon.sprite = GetListLocationIcon(location, controller);
ClearList(); ClearList();
scrollRect.content.sizeDelta = new Vector2(scrollRect.content.sizeDelta.x, 140 * cards.Count);
if (ShouldUseExtraDeckGrid())
{
RefreshExtraDeckGrid();
return;
}
scrollRect.content.sizeDelta = new Vector2(scrollRect.content.sizeDelta.x, SingleColumnItemStep * cards.Count);
for (int i = 0; i < cards.Count; i++) for (int i = 0; i < cards.Count; i++)
{ {
var go = Instantiate(item); var go = Instantiate(item);
go.SetActive(true); go.SetActive(true);
cardObjs.Add(go); cardObjs.Add(go);
go.transform.SetParent(scrollRect.content, false); go.transform.SetParent(scrollRect.content, false);
go.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, -140 * (cards.Count - 1 - i)); go.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, -SingleColumnItemStep * (cards.Count - 1 - i));
var mono = go.GetComponent<CardListItem>();
mono.card = cards[i];
}
}
void RefreshExtraDeckGrid()
{
var rowCount = Mathf.CeilToInt(cards.Count / (float)ExtraDeckColumns);
var usableWidth = Mathf.Max(ExtraDeckBaseItemWidth,
baseRect.rect.width - ExtraDeckScrollbarWidth - ExtraDeckHorizontalInset * 2f);
var itemScale = Mathf.Clamp(
(usableWidth - ExtraDeckHorizontalGap * (ExtraDeckColumns - 1)) / (ExtraDeckBaseItemWidth * ExtraDeckColumns),
0.35f, 1f);
var scaledItemWidth = ExtraDeckBaseItemWidth * itemScale;
var scaledItemHeight = ExtraDeckVisualItemHeight * itemScale;
var rowHeight = scaledItemHeight + ExtraDeckVerticalGap;
var usedWidth = scaledItemWidth * ExtraDeckColumns + ExtraDeckHorizontalGap * (ExtraDeckColumns - 1);
var startX = Mathf.Max(0f, (usableWidth - usedWidth) * 0.5f) + ExtraDeckHorizontalInset;
scrollRect.content.sizeDelta = new Vector2(scrollRect.content.sizeDelta.x, rowHeight * rowCount);
AddExtraDeckRowLines(rowCount, usableWidth, rowHeight);
for (int i = 0; i < cards.Count; i++)
{
var go = Instantiate(item);
go.SetActive(true);
cardObjs.Add(go);
go.transform.SetParent(scrollRect.content, false);
var visualIndex = cards.Count - 1 - i;
var row = visualIndex / ExtraDeckColumns;
var column = visualIndex % ExtraDeckColumns;
var rect = go.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0f, 1f);
rect.anchorMax = new Vector2(0f, 1f);
rect.pivot = new Vector2(0f, 1f);
rect.sizeDelta = new Vector2(ExtraDeckBaseItemWidth, ExtraDeckRowLineHeight);
rect.localScale = Vector3.one * itemScale;
rect.anchoredPosition = new Vector2(
startX + column * (scaledItemWidth + ExtraDeckHorizontalGap),
-row * rowHeight);
if (go.TryGetComponent(out Image cardLineImage))
{
var c = cardLineImage.color;
c.a = 0f;
cardLineImage.color = c;
}
var mono = go.GetComponent<CardListItem>(); var mono = go.GetComponent<CardListItem>();
mono.card = cards[i]; mono.card = cards[i];
} }
} }
void AddExtraDeckRowLines(int rowCount, float usableWidth, float rowHeight)
{
var lineSprite = item != null && item.TryGetComponent(out Image itemBg) ? itemBg.sprite : null;
for (int i = 0; i <= rowCount; i++)
{
var line = new GameObject($"ExtraDeckRowLine_{i}", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
line.transform.SetParent(scrollRect.content, false);
cardObjs.Add(line);
var lineRect = line.GetComponent<RectTransform>();
lineRect.anchorMin = new Vector2(0f, 1f);
lineRect.anchorMax = new Vector2(0f, 1f);
lineRect.pivot = new Vector2(0f, 1f);
lineRect.sizeDelta = new Vector2(usableWidth, ExtraDeckRowLineHeight);
lineRect.anchoredPosition = new Vector2(ExtraDeckHorizontalInset, -i * rowHeight);
var image = line.GetComponent<Image>();
image.sprite = lineSprite;
image.type = Image.Type.Simple;
image.color = new Color(0.85f, 0.85f, 0.85f, 0.85f);
image.raycastTarget = false;
}
}
void EnsureWidthForLocation()
{
if (defaultBaseWidth < 0f)
defaultBaseWidth = baseRect.sizeDelta.x;
var targetWidth = defaultBaseWidth;
if (ShouldUseExtraDeckGrid())
targetWidth = Mathf.Max(defaultBaseWidth, GetExtraDeckRequiredWidth());
if (!Mathf.Approximately(baseRect.sizeDelta.x, targetWidth))
baseRect.sizeDelta = new Vector2(targetWidth, baseRect.sizeDelta.y);
}
float GetExtraDeckRequiredWidth()
{
return ExtraDeckScrollbarWidth
+ ExtraDeckHorizontalInset * 2f
+ ExtraDeckBaseItemWidth * ExtraDeckColumns
+ ExtraDeckHorizontalGap * (ExtraDeckColumns - 1);
}
bool ShouldUseExtraDeckGrid()
{
return IsToggleListLocation(location) && extraDeckGridMode;
}
void EnsureExtraDeckModeToggle()
{
TryBindExistingExtraDeckModeToggle();
if (extraDeckModeButton != null)
{
UpdateExtraDeckModeToggleLayout();
return;
}
var parent = baseRect;
if (parent == null)
return;
var go = new GameObject("ExtraDeckViewToggle", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button));
go.transform.SetParent(parent, false);
go.transform.SetAsLastSibling();
var rect = go.GetComponent<RectTransform>();
rect.anchorMin = new Vector2(0f, 1f);
rect.anchorMax = new Vector2(0f, 1f);
rect.pivot = new Vector2(0f, 1f);
rect.anchoredPosition = Vector2.zero;
rect.sizeDelta = Vector2.zero;
var bgImage = go.GetComponent<Image>();
var baseImage = baseRect != null ? baseRect.GetComponent<Image>() : null;
var blackBg = TextureManager.container != null ? TextureManager.container.black : null;
if (blackBg != null)
{
bgImage.sprite = blackBg;
bgImage.type = Image.Type.Simple;
bgImage.color = Color.white;
}
else if (baseImage != null)
{
bgImage.sprite = baseImage.sprite;
bgImage.type = baseImage.type;
bgImage.color = baseImage.color;
}
bgImage.raycastTarget = true;
extraDeckModeButton = go.GetComponent<Button>();
extraDeckModeButton.targetGraphic = bgImage;
extraDeckModeButton.onClick.AddListener(OnExtraDeckModeButtonClick);
var icon = new GameObject("Icon", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
icon.transform.SetParent(go.transform, false);
var iconRect = icon.GetComponent<RectTransform>();
iconRect.anchorMin = new Vector2(0.5f, 0.5f);
iconRect.anchorMax = new Vector2(0.5f, 0.5f);
iconRect.pivot = new Vector2(0.5f, 0.5f);
iconRect.anchoredPosition = Vector2.zero;
iconRect.sizeDelta = new Vector2(ExtraDeckToggleButtonIconSize, ExtraDeckToggleButtonIconSize);
extraDeckModeButtonIcon = icon.GetComponent<Image>();
extraDeckModeButtonIcon.preserveAspect = true;
extraDeckModeButtonIcon.color = Color.white;
extraDeckModeButtonIcon.raycastTarget = false;
EnsureExtraDeckModeToggleSeam(go.transform);
EnsureExtraDeckModeToggleJoinPatch(go.transform);
UpdateExtraDeckModeToggleLayout();
}
void TryBindExistingExtraDeckModeToggle()
{
if (extraDeckModeButton != null || baseRect == null)
return;
var existing = baseRect.Find("ExtraDeckViewToggle");
if (existing == null)
return;
extraDeckModeButton = existing.GetComponent<Button>();
if (extraDeckModeButton == null)
return;
var iconTransform = existing.Find("Icon");
if (iconTransform != null)
extraDeckModeButtonIcon = iconTransform.GetComponent<Image>();
EnsureExtraDeckModeToggleSeam(existing);
EnsureExtraDeckModeToggleJoinPatch(existing);
var bgImage = existing.GetComponent<Image>();
if (bgImage != null)
extraDeckModeButton.targetGraphic = bgImage;
extraDeckModeButton.onClick.RemoveListener(OnExtraDeckModeButtonClick);
extraDeckModeButton.onClick.AddListener(OnExtraDeckModeButtonClick);
}
void UpdateExtraDeckModeToggle()
{
if (extraDeckModeButton == null || extraDeckModeButtonIcon == null)
return;
UpdateExtraDeckModeToggleLayout();
var isToggleLocation = IsToggleListLocation(location);
extraDeckModeButton.gameObject.SetActive(isToggleLocation);
if (!isToggleLocation)
return;
if (ShouldUseExtraDeckGrid())
extraDeckModeButtonIcon.sprite = TextureManager.container.listViewIconDefault != null
? TextureManager.container.listViewIconDefault
: TextureManager.container.listMyDeck;
else
extraDeckModeButtonIcon.sprite = TextureManager.container.listViewIconExpand != null
? TextureManager.container.listViewIconExpand
: (controller == 0 ? TextureManager.container.listMyDeck : TextureManager.container.listOpDeck);
}
void OnExtraDeckModeButtonClick()
{
if (!IsToggleListLocation(location))
return;
extraDeckGridMode = !extraDeckGridMode;
RefreshList();
}
bool IsToggleListLocation(CardLocation targetLocation)
{
return (targetLocation & (CardLocation.Extra | CardLocation.Grave | CardLocation.Removed)) > 0;
}
float GetHiddenPosX()
{
return (baseRect.sizeDelta.x + HiddenPadding + GetToggleLeftProtrusion()) * Config.GetUIScale(1.18f)
+ SafeAreaAdapter.GetSafeAreaRightOffset();
}
float GetToggleLeftProtrusion()
{
if (extraDeckModeButton == null || !extraDeckModeButton.gameObject.activeSelf)
return 0f;
if (extraDeckModeButton.transform is RectTransform rt)
return Mathf.Max(0f, -rt.anchoredPosition.x);
return Mathf.Max(0f, -GetExtraDeckToggleAnchoredX());
}
float GetExtraDeckToggleAnchoredX()
{
return -ExtraDeckToggleButtonWidth + ExtraDeckToggleButtonOverlap;
}
float GetExtraDeckToggleAdornmentAnchoredX()
{
// Lock the visible seam line to the toggle start (left edge).
return -ExtraDeckToggleAdornmentVisibleStartX;
}
void UpdateExtraDeckModeToggleLayout()
{
if (extraDeckModeButton != null && extraDeckModeButton.transform is RectTransform buttonRect)
{
buttonRect.anchoredPosition = new Vector2(GetExtraDeckToggleAnchoredX(), -ExtraDeckToggleButtonTopInset);
buttonRect.sizeDelta = new Vector2(ExtraDeckToggleButtonWidth, ExtraDeckToggleButtonHeight);
}
if (extraDeckModeButtonSeamRect != null)
{
extraDeckModeButtonSeamRect.anchoredPosition =
new Vector2(GetExtraDeckToggleAdornmentAnchoredX(), ExtraDeckToggleAdornmentOffsetY);
extraDeckModeButtonSeamRect.sizeDelta =
new Vector2(ExtraDeckToggleAdornmentWidth, ExtraDeckToggleAdornmentHeight);
}
if (extraDeckModeButtonJoinPatchRect != null)
{
extraDeckModeButtonJoinPatchRect.anchoredPosition =
new Vector2(ExtraDeckToggleJoinPatchOffsetX, ExtraDeckToggleJoinPatchOffsetY);
extraDeckModeButtonJoinPatchRect.sizeDelta =
new Vector2(ExtraDeckToggleJoinPatchWidth, ExtraDeckToggleJoinPatchHeight);
}
if (extraDeckModeButtonJoinPatchTopLineRect != null)
{
extraDeckModeButtonJoinPatchTopLineRect.anchoredPosition = Vector2.zero;
extraDeckModeButtonJoinPatchTopLineRect.sizeDelta = new Vector2(0f, ExtraDeckToggleJoinPatchTopLineHeight);
}
}
void EnsureExtraDeckModeToggleSeam(Transform parent)
{
extraDeckModeButtonSeamRect = null;
var seamSprite = GetToggleBackgroundSprite();
if (parent == null || seamSprite == null)
return;
RectTransform seamRect = null;
var seamTransform = parent.Find("Seam");
if (seamTransform != null)
{
seamTransform.gameObject.SetActive(true);
seamRect = seamTransform as RectTransform;
if (seamRect == null)
seamRect = seamTransform.GetComponent<RectTransform>();
}
if (seamRect == null)
{
var seam = new GameObject("Seam", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
seam.transform.SetParent(parent, false);
seam.transform.SetAsFirstSibling();
seamRect = seam.GetComponent<RectTransform>();
}
seamRect.anchorMin = new Vector2(0f, 1f);
seamRect.anchorMax = new Vector2(0f, 1f);
seamRect.pivot = new Vector2(0f, 1f);
seamRect.anchoredPosition = Vector2.zero;
seamRect.sizeDelta = Vector2.zero;
var seamImage = seamRect.GetComponent<Image>();
if (seamImage == null)
seamImage = seamRect.gameObject.AddComponent<Image>();
seamImage.sprite = seamSprite;
seamImage.type = Image.Type.Simple;
seamImage.color = Color.white;
seamImage.raycastTarget = false;
extraDeckModeButtonSeamRect = seamRect;
var middleMaskTransform = seamRect.Find("MiddleMask");
if (middleMaskTransform != null)
middleMaskTransform.gameObject.SetActive(false);
}
void EnsureExtraDeckModeToggleJoinPatch(Transform parent)
{
extraDeckModeButtonJoinPatchRect = null;
extraDeckModeButtonJoinPatchTopLineRect = null;
if (parent == null)
return;
RectTransform patchRect = null;
var patchTransform = parent.Find("JoinPatch");
if (patchTransform != null)
{
patchTransform.gameObject.SetActive(true);
patchRect = patchTransform as RectTransform;
if (patchRect == null)
patchRect = patchTransform.GetComponent<RectTransform>();
}
if (patchRect == null)
{
var patch = new GameObject("JoinPatch", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
patch.transform.SetParent(parent, false);
patch.transform.SetSiblingIndex(0);
patchRect = patch.GetComponent<RectTransform>();
}
patchRect.anchorMin = new Vector2(0f, 1f);
patchRect.anchorMax = new Vector2(0f, 1f);
patchRect.pivot = new Vector2(0f, 1f);
var patchImage = patchRect.GetComponent<Image>();
var blackBg = TextureManager.container != null ? TextureManager.container.black : null;
if (blackBg != null)
{
patchImage.sprite = blackBg;
patchImage.type = Image.Type.Simple;
patchImage.color = Color.white;
}
else
{
patchImage.sprite = null;
patchImage.color = Color.black;
}
patchImage.raycastTarget = false;
RectTransform topLineRect = null;
var topLineTransform = patchRect.Find("TopLine");
if (topLineTransform != null)
{
topLineTransform.gameObject.SetActive(true);
topLineRect = topLineTransform as RectTransform;
if (topLineRect == null)
topLineRect = topLineTransform.GetComponent<RectTransform>();
}
if (topLineRect == null)
{
var topLine = new GameObject("TopLine", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
topLine.transform.SetParent(patchRect, false);
topLineRect = topLine.GetComponent<RectTransform>();
}
topLineRect.anchorMin = new Vector2(0f, 1f);
topLineRect.anchorMax = new Vector2(1f, 1f);
topLineRect.pivot = new Vector2(0.5f, 1f);
var topLineImage = topLineRect.GetComponent<Image>();
if (blackBg != null)
{
topLineImage.sprite = blackBg;
topLineImage.type = Image.Type.Simple;
}
else
{
topLineImage.sprite = null;
}
topLineImage.color = new Color(0.78f, 0.78f, 0.78f, 1f);
topLineImage.raycastTarget = false;
extraDeckModeButtonJoinPatchRect = patchRect;
extraDeckModeButtonJoinPatchTopLineRect = topLineRect;
}
Sprite GetToggleBackgroundSprite()
{
return TextureManager.container != null ? TextureManager.container.listCardStatsBase : null;
}
void ClearList() void ClearList()
{ {
foreach (var obj in cardObjs) foreach (var obj in cardObjs)
......
...@@ -656,13 +656,13 @@ namespace MDPro3.Duel ...@@ -656,13 +656,13 @@ namespace MDPro3.Duel
MessageManager.Cast(InterString.Get("请联系开发者修复这张特殊胜利的卡。")); MessageManager.Cast(InterString.Get("请联系开发者修复这张特殊胜利的卡。"));
} }
// Start win/lose field animation first, then show result text while it is ongoing.
duelBGManager.ShowBGEnd(duelResult);
await duelBGManager.ShowDuelResultText(duelText); await duelBGManager.ShowDuelResultText(duelText);
MessageManager.Cast(endingReason); MessageManager.Cast(endingReason);
if (condition != Condition.Replay) if (condition != Condition.Replay)
Core.GetUI<OcgCoreUI>().ShowSaveReplay(); Core.GetUI<OcgCoreUI>().ShowSaveReplay();
duelBGManager.ShowBGEnd(duelResult);
} }
protected override UniTask GameMessage_UpdateData(BinaryReader reader) protected override UniTask GameMessage_UpdateData(BinaryReader reader)
......
...@@ -8,6 +8,8 @@ namespace MDPro3.Duel.YGOSharp ...@@ -8,6 +8,8 @@ namespace MDPro3.Duel.YGOSharp
public IList<int> BannedIds { get; private set; } public IList<int> BannedIds { get; private set; }
public IList<int> LimitedIds { get; private set; } public IList<int> LimitedIds { get; private set; }
public IList<int> SemiLimitedIds { get; private set; } public IList<int> SemiLimitedIds { get; private set; }
public IList<int> UnlimitedIds { get; private set; }
public bool WhitelistOnly { get; private set; }
public uint Hash { get; private set; } public uint Hash { get; private set; }
public string Name = ""; public string Name = "";
...@@ -16,6 +18,8 @@ namespace MDPro3.Duel.YGOSharp ...@@ -16,6 +18,8 @@ namespace MDPro3.Duel.YGOSharp
BannedIds = new List<int>(); BannedIds = new List<int>();
LimitedIds = new List<int>(); LimitedIds = new List<int>();
SemiLimitedIds = new List<int>(); SemiLimitedIds = new List<int>();
UnlimitedIds = new List<int>();
WhitelistOnly = false;
Hash = 0x7dfcee6a; Hash = 0x7dfcee6a;
} }
...@@ -37,7 +41,9 @@ namespace MDPro3.Duel.YGOSharp ...@@ -37,7 +41,9 @@ namespace MDPro3.Duel.YGOSharp
return 1; return 1;
if (SemiLimitedIds.Contains(cardId)) if (SemiLimitedIds.Contains(cardId))
return 2; return 2;
if (UnlimitedIds.Contains(cardId))
return 3; return 3;
return WhitelistOnly ? 0 : 3;
} }
else else
{ {
...@@ -47,14 +53,24 @@ namespace MDPro3.Duel.YGOSharp ...@@ -47,14 +53,24 @@ namespace MDPro3.Duel.YGOSharp
return 1; return 1;
if (SemiLimitedIds.Contains(al)) if (SemiLimitedIds.Contains(al))
return 2; return 2;
if (UnlimitedIds.Contains(al))
return 3; return 3;
return WhitelistOnly ? 0 : 3;
} }
} }
public void EnableWhitelistMode()
{
if (WhitelistOnly)
return;
WhitelistOnly = true;
Hash ^= 0x0f0f0f0f;
}
public void Add(int cardId, int quantity) public void Add(int cardId, int quantity)
{ {
if (quantity < 0 || quantity > 2) if (quantity < 0 || quantity > 3)
return; return;
switch (quantity) switch (quantity)
{ {
...@@ -67,6 +83,9 @@ namespace MDPro3.Duel.YGOSharp ...@@ -67,6 +83,9 @@ namespace MDPro3.Duel.YGOSharp
case 2: case 2:
SemiLimitedIds.Add(cardId); SemiLimitedIds.Add(cardId);
break; break;
case 3:
UnlimitedIds.Add(cardId);
break;
} }
uint code = (uint)cardId; uint code = (uint)cardId;
Hash = Hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + quantity)) | (code >> (5 - quantity))); Hash = Hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + quantity)) | (code >> (5 - quantity)));
......
using Ionic.Zip; using Ionic.Zip;
using MDPro3.Servant; using MDPro3.Servant;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text;
namespace MDPro3.Duel.YGOSharp namespace MDPro3.Duel.YGOSharp
{ {
...@@ -9,6 +11,9 @@ namespace MDPro3.Duel.YGOSharp ...@@ -9,6 +11,9 @@ namespace MDPro3.Duel.YGOSharp
{ {
public static List<Banlist> Banlists { get; private set; } public static List<Banlist> Banlists { get; private set; }
public static string EmptyBanlistName = "N/A"; public static string EmptyBanlistName = "N/A";
private static bool localServerLflistInjected;
private static string localServerLflistBackupContent;
private const string LfListFileName = "lflist.conf";
public static void Initialize() public static void Initialize()
{ {
...@@ -54,6 +59,110 @@ namespace MDPro3.Duel.YGOSharp ...@@ -54,6 +59,110 @@ namespace MDPro3.Duel.YGOSharp
Banlists.Add(current); Banlists.Add(current);
} }
public static void PrepareLocalServerLflist()
{
if (localServerLflistInjected)
return;
if (!Config.GetBool("Expansions", true))
return;
try
{
if (!File.Exists(Program.PATH_LFLIST))
return;
localServerLflistBackupContent = File.ReadAllText(Program.PATH_LFLIST);
var mergedContent = BuildMergedLflistContent();
if (string.IsNullOrEmpty(mergedContent) || mergedContent == localServerLflistBackupContent)
{
localServerLflistBackupContent = null;
return;
}
File.WriteAllText(Program.PATH_LFLIST, mergedContent);
localServerLflistInjected = true;
}
catch (Exception e)
{
localServerLflistBackupContent = null;
localServerLflistInjected = false;
UnityEngine.Debug.LogError("Failed to prepare LAN lflist.conf.");
UnityEngine.Debug.LogException(e);
}
}
public static void RestoreLocalServerLflist()
{
if (!localServerLflistInjected)
return;
try
{
if (localServerLflistBackupContent != null)
File.WriteAllText(Program.PATH_LFLIST, localServerLflistBackupContent);
}
catch (Exception e)
{
UnityEngine.Debug.LogError("Failed to restore original lflist.conf.");
UnityEngine.Debug.LogException(e);
}
finally
{
localServerLflistBackupContent = null;
localServerLflistInjected = false;
}
}
private static string BuildMergedLflistContent()
{
StringBuilder builder = new StringBuilder();
var confPath = Program.PATH_EXPANSIONS + LfListFileName;
AppendLflistFromFile(builder, confPath);
foreach (var zip in ZipHelper.zips)
{
if (zip.Name.ToLower().EndsWith("script.zip"))
continue;
foreach (var file in zip.EntryFileNames)
{
if (!file.ToLower().EndsWith(LfListFileName))
continue;
var entry = zip[file];
using (var memoryStream = new MemoryStream())
{
entry.Extract(memoryStream);
memoryStream.Position = 0;
using (var reader = new StreamReader(memoryStream))
AppendLflistText(builder, reader.ReadToEnd());
}
}
}
AppendLflistFromFile(builder, Program.PATH_LFLIST);
return builder.ToString();
}
private static void AppendLflistFromFile(StringBuilder builder, string path)
{
if (!File.Exists(path))
return;
AppendLflistText(builder, File.ReadAllText(path));
}
private static void AppendLflistText(StringBuilder builder, string text)
{
if (string.IsNullOrWhiteSpace(text))
return;
if (builder.Length > 0 && builder[builder.Length - 1] != '\n')
builder.AppendLine();
builder.Append(text);
if (builder.Length > 0 && builder[builder.Length - 1] != '\n')
builder.AppendLine();
}
public static void InitializeFromReader(StreamReader reader) public static void InitializeFromReader(StreamReader reader)
{ {
Banlist current = null; Banlist current = null;
...@@ -73,6 +182,12 @@ namespace MDPro3.Duel.YGOSharp ...@@ -73,6 +182,12 @@ namespace MDPro3.Duel.YGOSharp
Banlists.Add(current); Banlists.Add(current);
continue; continue;
} }
if (line.StartsWith("$"))
{
if (current != null && line.Equals("$whitelist", StringComparison.OrdinalIgnoreCase))
current.EnableWhitelistMode();
continue;
}
if (!line.Contains(" ")) if (!line.Contains(" "))
continue; continue;
if (current == null) if (current == null)
......
...@@ -6,6 +6,7 @@ using Mono.Data.Sqlite; ...@@ -6,6 +6,7 @@ using Mono.Data.Sqlite;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Globalization;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using YGOSharp.OCGWrapper; using YGOSharp.OCGWrapper;
...@@ -20,6 +21,9 @@ namespace MDPro3.Duel.YGOSharp ...@@ -20,6 +21,9 @@ namespace MDPro3.Duel.YGOSharp
public static IDictionary<int, Card> _cards = new Dictionary<int, Card>(); public static IDictionary<int, Card> _cards = new Dictionary<int, Card>();
public static IDictionary<int, Card> _cardsForRender = new Dictionary<int, Card>(); public static IDictionary<int, Card> _cardsForRender = new Dictionary<int, Card>();
private static readonly CompareInfo SearchCompareInfo = CultureInfo.InvariantCulture.CompareInfo;
private const CompareOptions SearchCompareOptions =
CompareOptions.IgnoreCase | CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType;
public static List<string> setNameHead = new() public static List<string> setNameHead = new()
{ {
...@@ -59,83 +63,55 @@ namespace MDPro3.Duel.YGOSharp ...@@ -59,83 +63,55 @@ namespace MDPro3.Duel.YGOSharp
{ {
nullName = InterString.Get("未知卡片"); nullName = InterString.Get("未知卡片");
nullString = string.Empty; nullString = string.Empty;
; IDictionary<int, Card> previousCards = _cards;
string language = Language.GetConfig(); IDictionary<int, Card> previousRenderCards = _cardsForRender;
string databaseFullPath = Program.PATH_LOCALES + language + "/cards.cdb";
if (!File.Exists(databaseFullPath)) var loadedCards = new Dictionary<int, Card>(Math.Max(previousCards?.Count ?? 0, 16384));
databaseFullPath = Program.PATH_LOCALES + "zh-CN/cards.cdb"; var loadedRenderCards = new Dictionary<int, Card>(Math.Max(previousRenderCards?.Count ?? 0, 16384));
_cards.Clear();
LoadCDB(databaseFullPath); bool loadedMain = TryLoadCardsForLanguage(loadedCards, Language.GetConfig(), render: false);
if (Config.Get("Expansions", "1") == "1") bool loadedRender = TryLoadCardsForLanguage(loadedRenderCards, Language.GetCardConfig(), render: true);
{
foreach (var cdb in Directory.GetFiles("Expansions", "*.cdb")) if (!loadedMain || loadedCards.Count == 0)
LoadCDB(cdb);
foreach (var zip in ZipHelper.zips)
{
if (zip.Name.ToLower().EndsWith("script.zip"))
continue;
foreach (var file in zip.EntryFileNames)
{ {
if (file.ToLower().EndsWith(".cdb")) if (string.IsNullOrEmpty(MDPro3.MessageManager.messageFromSubString))
{ {
var e = zip[file]; MDPro3.MessageManager.messageFromSubString =
if (!Directory.Exists(Program.PATH_TEMP_FOLDER)) InterString.Get("Failed to load card database. Some cards may be shown as unknown.");
Directory.CreateDirectory(Program.PATH_TEMP_FOLDER);
var tempFile = Path.Combine(Path.GetFullPath(Program.PATH_TEMP_FOLDER), file);
e.Extract(Path.GetFullPath(Program.PATH_TEMP_FOLDER), ExtractExistingFileAction.OverwriteSilently);
LoadCDB(tempFile, isPreCards : Path.GetFileName(zip.Name) == "ygopro-super-pre.ypk" && file.ToLower().StartsWith("test-release"));
File.Delete(tempFile);
}
} }
if (previousCards != null && previousCards.Count > 0)
_cards = previousCards;
else
_cards = loadedCards;
if (previousRenderCards != null && previousRenderCards.Count > 0)
_cardsForRender = previousRenderCards;
else
_cardsForRender = loadedRenderCards;
return;
} }
if (!loadedRender)
{
if (previousRenderCards != null && previousRenderCards.Count > 0)
loadedRenderCards = new Dictionary<int, Card>(previousRenderCards);
else
loadedRenderCards = new Dictionary<int, Card>(loadedCards);
} }
_cards = loadedCards;
_cardsForRender = loadedRenderCards;
UpdateSetNames(); UpdateSetNames();
PacksManager.Initialize(); PacksManager.Initialize();
_cardsForRender.Clear();
var cardLanguage = Language.GetCardConfig();
databaseFullPath = Program.PATH_LOCALES + cardLanguage + "/cards.cdb";
if (!File.Exists(databaseFullPath))
databaseFullPath = Program.PATH_LOCALES + "zh-CN/cards.cdb";
LoadCDB(databaseFullPath, true);
if (Config.Get("Expansions", "1") == "1")
{
foreach (var cdb in Directory.GetFiles("Expansions", "*.cdb"))
LoadCDB(cdb, true);
foreach (var zip in ZipHelper.zips)
{
if (zip.Name.ToLower().EndsWith("script.zip"))
continue;
foreach (var file in zip.EntryFileNames)
{
if (file.ToLower().EndsWith(".cdb"))
{
var e = zip[file];
if (!Directory.Exists(Program.PATH_TEMP_FOLDER))
Directory.CreateDirectory(Program.PATH_TEMP_FOLDER);
var tempFile = Path.Combine(Path.GetFullPath(Program.PATH_TEMP_FOLDER), file);
e.Extract(Path.GetFullPath(Program.PATH_TEMP_FOLDER), ExtractExistingFileAction.OverwriteSilently);
LoadCDB(tempFile, true, isPreCards: Path.GetFileName(zip.Name) == "ygopro-super-pre.ypk");
File.Delete(tempFile);
}
}
}
}
} }
internal static void LoadCDB(string databaseFullPath, bool render = false, bool isPreCards = false) internal static void LoadCDB(string databaseFullPath, bool render = false, bool isPreCards = false)
{ {
using SqliteConnection connection = new("Data Source=" + databaseFullPath); var targetCards = render ? _cardsForRender : _cards;
connection.Open(); TryLoadCDB(databaseFullPath, targetCards, isPreCards, render, optionalDatabase: false);
using IDbCommand command =
new SqliteCommand("SELECT datas.*, texts.* FROM datas,texts WHERE datas.id=texts.id;", connection);
using IDataReader reader = command.ExecuteReader();
while (reader.Read())
{
LoadCard(reader, render, isPreCards);
}
} }
internal static void UpdateSetNames() internal static void UpdateSetNames()
...@@ -212,26 +188,117 @@ namespace MDPro3.Duel.YGOSharp ...@@ -212,26 +188,117 @@ namespace MDPro3.Duel.YGOSharp
return returnValue; return returnValue;
} }
private static void LoadCard(IDataRecord reader, bool render = false, bool isPreCards = false) private static bool TryLoadCardsForLanguage(IDictionary<int, Card> targetCards, string language, bool render)
{ {
Card card = new(reader) string databaseFullPath = ResolveCardsDatabasePath(language);
if (!TryLoadCDB(databaseFullPath, targetCards, isPreCards: false, render, optionalDatabase: false))
return false;
if (Config.Get("Expansions", "1") != "1")
return true;
foreach (var cdb in Directory.GetFiles("Expansions", "*.cdb"))
TryLoadCDB(cdb, targetCards, isPreCards: false, render, optionalDatabase: true);
foreach (var zip in ZipHelper.zips)
{ {
isPre = isPreCards if (zip.Name.ToLower().EndsWith("script.zip"))
}; continue;
if (!render)
foreach (var file in zip.EntryFileNames)
{
if (!file.ToLower().EndsWith(".cdb"))
continue;
string tempRoot = Path.GetFullPath(Program.PATH_TEMP_FOLDER);
string tempFile = Path.Combine(tempRoot, file);
bool isPreCards = false;
try
{
if (!Directory.Exists(tempRoot))
Directory.CreateDirectory(tempRoot);
zip[file].Extract(tempRoot, ExtractExistingFileAction.OverwriteSilently);
bool fromPrereleasePack = Path.GetFileName(zip.Name)
.Equals("ygopro-super-pre.ypk", StringComparison.OrdinalIgnoreCase);
isPreCards = fromPrereleasePack && (render || file.ToLower().StartsWith("test-release"));
TryLoadCDB(tempFile, targetCards, isPreCards, render, optionalDatabase: true);
}
catch (Exception)
{ {
//if (!_cards.ContainsKey(card.Id))
// _cards.Add(card.Id, card);
_cards[card.Id] = card;
} }
else finally
{
try
{
if (File.Exists(tempFile))
File.Delete(tempFile);
}
catch (Exception)
{
}
}
}
}
return true;
}
private static string ResolveCardsDatabasePath(string language)
{
string databaseFullPath = Program.PATH_LOCALES + language + "/cards.cdb";
if (!File.Exists(databaseFullPath))
databaseFullPath = Program.PATH_LOCALES + Language.SimplifiedChinese + "/cards.cdb";
return databaseFullPath;
}
private static bool TryLoadCDB(
string databaseFullPath,
IDictionary<int, Card> targetCards,
bool isPreCards,
bool render,
bool optionalDatabase)
{
try
{
using SqliteConnection connection = new("Data Source=" + databaseFullPath);
connection.Open();
using IDbCommand command =
new SqliteCommand("SELECT datas.*, texts.* FROM datas,texts WHERE datas.id=texts.id;", connection);
using IDataReader reader = command.ExecuteReader();
while (reader.Read())
{
try
{
LoadCard(reader, targetCards, isPreCards);
}
catch (Exception)
{
}
}
return true;
}
catch (Exception)
{ {
//if (!_cardsForRender.ContainsKey(card.Id)) return false;
// _cardsForRender.Add(card.Id, card);
_cardsForRender[card.Id] = card;
} }
} }
private static void LoadCard(IDataRecord reader, IDictionary<int, Card> targetCards, bool isPreCards = false)
{
Card card = new(reader)
{
isPre = isPreCards
};
targetCards[card.Id] = card;
}
public static List<string> GetMiddleStrings(string str, string start, string end) public static List<string> GetMiddleStrings(string str, string start, string end)
{ {
List<string> returnValue = new List<string>(); List<string> returnValue = new List<string>();
...@@ -269,6 +336,30 @@ namespace MDPro3.Duel.YGOSharp ...@@ -269,6 +336,30 @@ namespace MDPro3.Duel.YGOSharp
return returnValue; return returnValue;
} }
private static bool MatchWithSearchOptions(string source, string keyword)
{
if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(keyword))
return false;
try
{
if (Regex.Replace(source, keyword, "miaowu", RegexOptions.IgnoreCase) != source)
return true;
}
catch (ArgumentException)
{
// Keep searching with a literal fallback when regex input is invalid.
}
return SearchCompareInfo.IndexOf(source, keyword, SearchCompareOptions) >= 0;
}
private static bool MatchCardId(int cardId, string keyword)
{
return !string.IsNullOrEmpty(keyword)
&& SearchCompareInfo.Compare(cardId.ToString(), keyword, SearchCompareOptions) == 0;
}
internal static List<Card> Search internal static List<Card> Search
( (
string getName, string getName,
...@@ -278,7 +369,7 @@ namespace MDPro3.Duel.YGOSharp ...@@ -278,7 +369,7 @@ namespace MDPro3.Duel.YGOSharp
) )
{ {
var returnValue = new List<Card>(); var returnValue = new List<Card>();
string[] strings = getName.Split(' '); string[] strings = getName.Split(new[] { ' ', '\u3000' }, StringSplitOptions.None);
nameInSearch = getName; nameInSearch = getName;
foreach (var item in _cards) foreach (var item in _cards)
{ {
...@@ -290,7 +381,7 @@ namespace MDPro3.Duel.YGOSharp ...@@ -290,7 +381,7 @@ namespace MDPro3.Duel.YGOSharp
{ {
if (s.StartsWith("@")) if (s.StartsWith("@"))
{ {
if (Regex.Replace(card.strSetName, s.Substring(1, s.Length - 1), "miaowu", RegexOptions.IgnoreCase) == card.strSetName) if (!MatchWithSearchOptions(card.strSetName, s.Substring(1, s.Length - 1)))
{ {
pass = false; pass = false;
break; break;
...@@ -298,10 +389,10 @@ namespace MDPro3.Duel.YGOSharp ...@@ -298,10 +389,10 @@ namespace MDPro3.Duel.YGOSharp
} }
else if ( else if (
s != "" s != ""
&& Regex.Replace(card.Name, s, "miaowu", RegexOptions.IgnoreCase) == card.Name && !MatchWithSearchOptions(card.Name, s)
&& Regex.Replace(card.Desc, s, "miaowu", RegexOptions.IgnoreCase) == card.Desc && !MatchWithSearchOptions(card.Desc, s)
&& Regex.Replace(card.strSetName, s, "miaowu", RegexOptions.IgnoreCase) == card.strSetName && !MatchWithSearchOptions(card.strSetName, s)
&& card.Id.ToString() != s && !MatchCardId(card.Id, s)
) )
{ {
pass = false; pass = false;
...@@ -553,9 +644,9 @@ namespace MDPro3.Duel.YGOSharp ...@@ -553,9 +644,9 @@ namespace MDPro3.Duel.YGOSharp
{ {
Card card = item.Value; Card card = item.Value;
if(announced == "" if(announced == ""
|| Regex.Replace(card.Name, announced, "miaowu", RegexOptions.IgnoreCase) != card.Name || MatchWithSearchOptions(card.Name, announced)
|| Regex.Replace(card.strSetName, announced, "miaowu", RegexOptions.IgnoreCase) != card.strSetName || MatchWithSearchOptions(card.strSetName, announced)
|| card.Id.ToString() == announced) || MatchCardId(card.Id, announced))
{ {
if(searchCodes.Count == 0 || IsDeclarable(card, searchCodes)) if(searchCodes.Count == 0 || IsDeclarable(card, searchCodes))
returnValue.Add(card); returnValue.Add(card);
......
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using MDPro3.Duel.YGOSharp;
namespace MDPro3.Net namespace MDPro3.Net
{ {
...@@ -20,16 +21,30 @@ namespace MDPro3.Net ...@@ -20,16 +21,30 @@ namespace MDPro3.Net
StopServer(); StopServer();
serverThread = new Thread(() => serverThread = new Thread(() =>
{
try
{ {
Dll.start_server(args); Dll.start_server(args);
}
finally
{
BanlistManager.RestoreLocalServerLflist();
}
}); });
serverThread.Start(); serverThread.Start();
} }
public static void StopServer() public static void StopServer()
{
try
{ {
Dll.stop_server(); Dll.stop_server();
}
finally
{
serverThread?.Abort(); serverThread?.Abort();
BanlistManager.RestoreLocalServerLflist();
}
} }
public static bool ServerRunning() public static bool ServerRunning()
......
...@@ -25,8 +25,8 @@ namespace MDPro3 ...@@ -25,8 +25,8 @@ namespace MDPro3
public static void Initialize() public static void Initialize()
{ {
translations.Clear(); translations.Clear();
translationsForRender.Clear(); translationsForRender = new Dictionary<string, string>();
translationsForPrerelease.Clear(); translationsForPrerelease = new Dictionary<string, string>();
path = Program.PATH_LOCALES + Language.GetConfig() + PATH_CONF_FILE; path = Program.PATH_LOCALES + Language.GetConfig() + PATH_CONF_FILE;
if (!File.Exists(path)) if (!File.Exists(path))
......
...@@ -298,6 +298,10 @@ namespace MDPro3 ...@@ -298,6 +298,10 @@ namespace MDPro3
public Sprite listOpRemoved; public Sprite listOpRemoved;
public Sprite listMyXyz; public Sprite listMyXyz;
public Sprite listOpXyz; public Sprite listOpXyz;
public Sprite listSingleColumn;
public Sprite listViewIconExpand;
public Sprite listViewIconDefault;
public Sprite listCardStatsBase;
[Header("Card Affect")] [Header("Card Affect")]
public Sprite CardAffectDisable; public Sprite CardAffectDisable;
......
...@@ -131,6 +131,7 @@ namespace MDPro3.Servant ...@@ -131,6 +131,7 @@ namespace MDPro3.Servant
public static float nextNegateAction_AdditionalTime; public static float nextNegateAction_AdditionalTime;
public static ElementObjectManager nextNegateAction_AdditionalManager; public static ElementObjectManager nextNegateAction_AdditionalManager;
public static Action startCard; public static Action startCard;
public Action onSurrenderConfirmed;
public static Material myProtector; public static Material myProtector;
public static Material opProtector; public static Material opProtector;
...@@ -653,11 +654,13 @@ namespace MDPro3.Servant ...@@ -653,11 +654,13 @@ namespace MDPro3.Servant
InterString.Get("是"), InterString.Get("是"),
InterString.Get("否") InterString.Get("否")
}; };
UIManager.ShowPopupYesOrNo(selections, ActionSurrender, null); UIManager.ShowPopupYesOrNo(selections, ActionSurrender, ActionCancelSurrender);
} }
private void ActionSurrender() private void ActionSurrender()
{ {
onSurrenderConfirmed?.Invoke();
onSurrenderConfirmed = null;
surrendered = true; surrendered = true;
if (TcpHelper.tcpClient != null && TcpHelper.tcpClient.Connected) if (TcpHelper.tcpClient != null && TcpHelper.tcpClient.Connected)
{ {
...@@ -670,6 +673,11 @@ namespace MDPro3.Servant ...@@ -670,6 +673,11 @@ namespace MDPro3.Servant
OnExit(); OnExit();
} }
private void ActionCancelSurrender()
{
onSurrenderConfirmed = null;
}
#endregion #endregion
#region Message #region Message
......
...@@ -51,6 +51,8 @@ namespace MDPro3.Servant ...@@ -51,6 +51,8 @@ namespace MDPro3.Servant
if (servantUI != null) if (servantUI != null)
RefreshDeckSelector(); RefreshDeckSelector();
// Re-roll random duel icon/frame/protector whenever returning to lobby.
_ = Program.instance.appearance.LoadSettingAssets();
StartCoroutine(RefreshMyCardAssets()); StartCoroutine(RefreshMyCardAssets());
} }
...@@ -145,6 +147,7 @@ namespace MDPro3.Servant ...@@ -145,6 +147,7 @@ namespace MDPro3.Servant
RoomServant.FromLocalHost = true; RoomServant.FromLocalHost = true;
RoomServant.FromHandTest = false; RoomServant.FromHandTest = false;
BanlistManager.PrepareLocalServerLflist();
YgoServer.StartServer(args); YgoServer.StartServer(args);
TcpHelper.LinkStart("127.0.0.1", Config.Get("DuelPlayerName0", Config.EMPTY_STRING), port.ToString(), string.Empty, true, null); TcpHelper.LinkStart("127.0.0.1", Config.Get("DuelPlayerName0", Config.EMPTY_STRING), port.ToString(), string.Empty, true, null);
} }
......
...@@ -67,6 +67,8 @@ namespace MDPro3.Servant ...@@ -67,6 +67,8 @@ namespace MDPro3.Servant
CoreShowing = 0; CoreShowing = 0;
Program.instance.ui_.chatPanel.Show(false); Program.instance.ui_.chatPanel.Show(false);
OcgCore.handler = Handler; OcgCore.handler = Handler;
// Re-roll random duel/watch icon & frame whenever entering a room.
_ = Program.instance.appearance.LoadSettingAssets();
GetUI<RoomServantUI>().RefreshDeckSelector(); GetUI<RoomServantUI>().RefreshDeckSelector();
} }
......
...@@ -47,6 +47,17 @@ namespace MDPro3.Servant ...@@ -47,6 +47,17 @@ namespace MDPro3.Servant
[HideInInspector] public SelectionToggle_Solo lastSoloItem; [HideInInspector] public SelectionToggle_Solo lastSoloItem;
private string lastSoloCommand = string.Empty;
private int lastSoloPort = 7911;
private int lastSoloLp = 8000;
private int lastSoloHand = 5;
private int lastSoloDraw = 1;
private bool lastSoloLockHand;
private bool lastSoloNoCheck;
private bool lastSoloNoShuffle;
private bool hasLastSoloLaunchConfig;
private bool retryLastSoloDuelWhenShown;
#region Servant #region Servant
public override int Depth => 3; public override int Depth => 3;
...@@ -59,6 +70,13 @@ namespace MDPro3.Servant ...@@ -59,6 +70,13 @@ namespace MDPro3.Servant
LoadBots(); LoadBots();
} }
protected override void ApplyShowArrangement(int preDepth)
{
base.ApplyShowArrangement(preDepth);
if (retryLastSoloDuelWhenShown)
StartCoroutine(RetryLastSoloDuelWhenReady());
}
protected override void FirstLoadEvent() protected override void FirstLoadEvent()
{ {
base.FirstLoadEvent(); base.FirstLoadEvent();
...@@ -164,7 +182,19 @@ namespace MDPro3.Servant ...@@ -164,7 +182,19 @@ namespace MDPro3.Servant
{ {
string aiCommand = GetWindBotCommand(aiCode, diyDeck); string aiCommand = GetWindBotCommand(aiCode, diyDeck);
if (!string.IsNullOrEmpty(aiCommand)) if (!string.IsNullOrEmpty(aiCommand))
Launch(aiCommand, GetUI<SoloSelectorUI>().IsLockHand(), GetUI<SoloSelectorUI>().IsNoCheck(), GetUI<SoloSelectorUI>().IsNoShuffle()); {
var ui = GetUI<SoloSelectorUI>();
var lockHand = ui.IsLockHand();
var noCheck = ui.IsNoCheck();
var noShuffle = ui.IsNoShuffle();
var duelPort = ui.GetPort();
var duelLp = ui.GetLP();
var duelHand = ui.GetHand();
var duelDraw = ui.GetDraw();
RememberLastSoloLaunch(aiCommand, duelPort, duelLp, duelHand, duelDraw, lockHand, noCheck, noShuffle);
LaunchWithConfig(aiCommand, duelPort, duelLp, duelHand, duelDraw, lockHand, noCheck, noShuffle);
}
} }
public void StartAIForRoom(int aiCode, bool diyDeck) public void StartAIForRoom(int aiCode, bool diyDeck)
...@@ -229,13 +259,60 @@ namespace MDPro3.Servant ...@@ -229,13 +259,60 @@ namespace MDPro3.Servant
} }
public void Launch(string command, bool lockHand, bool noCheck, bool noShuffle) public void Launch(string command, bool lockHand, bool noCheck, bool noShuffle)
{ {
port = GetUI<SoloSelectorUI>().GetPort().ToString(); var ui = GetUI<SoloSelectorUI>();
LaunchWithConfig(command, ui.GetPort(), ui.GetLP(), ui.GetHand(), ui.GetDraw(), lockHand, noCheck, noShuffle);
}
public bool CanRetryLastSoloDuel()
{
return hasLastSoloLaunchConfig;
}
public void QueueRetryLastSoloDuel()
{
if (!CanRetryLastSoloDuel())
return;
retryLastSoloDuelWhenShown = true;
}
private void RememberLastSoloLaunch(string command, int duelPort, int duelLp, int duelHand, int duelDraw
, bool lockHand, bool noCheck, bool noShuffle)
{
lastSoloCommand = command;
lastSoloPort = duelPort;
lastSoloLp = duelLp;
lastSoloHand = duelHand;
lastSoloDraw = duelDraw;
lastSoloLockHand = lockHand;
lastSoloNoCheck = noCheck;
lastSoloNoShuffle = noShuffle;
hasLastSoloLaunchConfig = true;
}
private IEnumerator RetryLastSoloDuelWhenReady()
{
yield return null;
while (showing && inTransition)
yield return null;
if (!showing || !retryLastSoloDuelWhenShown || !hasLastSoloLaunchConfig)
yield break;
retryLastSoloDuelWhenShown = false;
LaunchWithConfig(lastSoloCommand, lastSoloPort, lastSoloLp, lastSoloHand, lastSoloDraw
, lastSoloLockHand, lastSoloNoCheck, lastSoloNoShuffle);
}
private void LaunchWithConfig(string command, int duelPort, int duelLp, int duelHand, int duelDraw
, bool lockHand, bool noCheck, bool noShuffle)
{
port = duelPort.ToString();
string lp = GetUI<SoloSelectorUI>().GetLP().ToString(); string lp = duelLp.ToString();
string hand = GetUI<SoloSelectorUI>().GetHand().ToString(); string hand = duelHand.ToString();
string draw = GetUI<SoloSelectorUI>().GetDraw().ToString(); string draw = duelDraw.ToString();
string args = port + " -1 5 0 F " + (noCheck ? "T " : "F ") + (noShuffle ? "T " : "F ") + lp + " " + hand + " " + draw + " 0 0"; string args = port + " -1 5 0 F " + (noCheck ? "T " : "F ") + (noShuffle ? "T " : "F ") + lp + " " + hand + " " + draw + " 0 0";
if (TcpHelper.IsPortAvailable(int.Parse(port))) if (TcpHelper.IsPortAvailable(duelPort))
{ {
YgoServer.StartServer(args); YgoServer.StartServer(args);
RoomServant.FromSolo = true; RoomServant.FromSolo = true;
......
...@@ -419,7 +419,7 @@ namespace MDPro3.UI ...@@ -419,7 +419,7 @@ namespace MDPro3.UI
SpellTrapType.SetActive(true); SpellTrapType.SetActive(true);
IconSpellTrapType.sprite = TextureManager.container.GetCardSpellTrapTypeIcon(data); IconSpellTrapType.sprite = TextureManager.container.GetCardSpellTrapTypeIcon(data);
TextSpellTrapType.text TextSpellTrapType.text
= StringHelper.SecondType(data.Type) + StringHelper.MainType(data.Type); = data.GetSpellTrapType(true);
IconAtk.gameObject.SetActive(false); IconAtk.gameObject.SetActive(false);
IconDef.gameObject.SetActive(false); IconDef.gameObject.SetActive(false);
......
...@@ -234,8 +234,7 @@ namespace MDPro3.UI ...@@ -234,8 +234,7 @@ namespace MDPro3.UI
cardCollectionView.superScrollView.scrollRect.OnBeginDrag(eventData); cardCollectionView.superScrollView.scrollRect.OnBeginDrag(eventData);
dragStartPosition = eventData.position; dragStartPosition = eventData.position;
dragProcessing = true; dragProcessing = true;
//draging = !DeckEditor.useMobileLayout; draging = !DeckEditor.UseMobileLayout;
draging = false;
dragIni = false; dragIni = false;
} }
......
...@@ -46,6 +46,7 @@ namespace MDPro3.UI ...@@ -46,6 +46,7 @@ namespace MDPro3.UI
public string description; public string description;
public string path; public string path;
private bool loaded; private bool loaded;
private Material protectorMaterial;
private Coroutine refreshCoroutine; private Coroutine refreshCoroutine;
private Coroutine hideCoroutine; private Coroutine hideCoroutine;
...@@ -71,8 +72,13 @@ namespace MDPro3.UI ...@@ -71,8 +72,13 @@ namespace MDPro3.UI
if (path.StartsWith("Protector")) if (path.StartsWith("Protector"))
{ {
Protector.material = await ABLoader.LoadProtectorMaterial(itemID.ToString(), destroyCancellationToken); protectorMaterial = await ABLoader.LoadProtectorMaterial(itemID.ToString(), destroyCancellationToken);
Protector.material.renderQueue = 3000; if (protectorMaterial != null)
protectorMaterial.renderQueue = 3000;
// Use default UI material for list rendering so viewport/mask clipping works while scrolling.
Protector.texture = protectorMaterial == null ? null : protectorMaterial.mainTexture;
Protector.material = null;
Protector.color = Color.white; Protector.color = Color.white;
Icon.gameObject.SetActive(false); Icon.gameObject.SetActive(false);
} }
...@@ -150,7 +156,7 @@ namespace MDPro3.UI ...@@ -150,7 +156,7 @@ namespace MDPro3.UI
{ {
DeckEditor.Deck.Protector = itemID; DeckEditor.Deck.Protector = itemID;
Program.instance.deckEditor.GetUI<DeckEditorUI>().DeckView.SetDirty(true); Program.instance.deckEditor.GetUI<DeckEditorUI>().DeckView.SetDirty(true);
Program.instance.deckEditor.GetUI<DeckEditorUI>().IconProtector.material = Protector.material; Program.instance.deckEditor.GetUI<DeckEditorUI>().IconProtector.material = protectorMaterial;
} }
} }
else if (path.StartsWith("FieldIcon")) else if (path.StartsWith("FieldIcon"))
...@@ -211,38 +217,38 @@ namespace MDPro3.UI ...@@ -211,38 +217,38 @@ namespace MDPro3.UI
if (Appearance.player == "0") if (Appearance.player == "0")
{ {
if (Appearance.condition == Appearance.Condition.Duel) if (Appearance.condition == Appearance.Condition.Duel)
Appearance.duelProtector0 = Protector.material; Appearance.duelProtector0 = protectorMaterial;
else if (Appearance.condition == Appearance.Condition.Watch) else if (Appearance.condition == Appearance.Condition.Watch)
Appearance.watchProtector0 = Protector.material; Appearance.watchProtector0 = protectorMaterial;
else if (Appearance.condition == Appearance.Condition.Replay) else if (Appearance.condition == Appearance.Condition.Replay)
Appearance.replayProtector0 = Protector.material; Appearance.replayProtector0 = protectorMaterial;
} }
else if (Appearance.player == "1") else if (Appearance.player == "1")
{ {
if (Appearance.condition == Appearance.Condition.Duel) if (Appearance.condition == Appearance.Condition.Duel)
Appearance.duelProtector1 = Protector.material; Appearance.duelProtector1 = protectorMaterial;
else if (Appearance.condition == Appearance.Condition.Watch) else if (Appearance.condition == Appearance.Condition.Watch)
Appearance.watchProtector1 = Protector.material; Appearance.watchProtector1 = protectorMaterial;
else if (Appearance.condition == Appearance.Condition.Replay) else if (Appearance.condition == Appearance.Condition.Replay)
Appearance.replayProtector1 = Protector.material; Appearance.replayProtector1 = protectorMaterial;
} }
else if (Appearance.player == "0Tag") else if (Appearance.player == "0Tag")
{ {
if (Appearance.condition == Appearance.Condition.Duel) if (Appearance.condition == Appearance.Condition.Duel)
Appearance.duelProtector0Tag = Protector.material; Appearance.duelProtector0Tag = protectorMaterial;
else if (Appearance.condition == Appearance.Condition.Watch) else if (Appearance.condition == Appearance.Condition.Watch)
Appearance.watchProtector0Tag = Protector.material; Appearance.watchProtector0Tag = protectorMaterial;
else if (Appearance.condition == Appearance.Condition.Replay) else if (Appearance.condition == Appearance.Condition.Replay)
Appearance.replayProtector0Tag = Protector.material; Appearance.replayProtector0Tag = protectorMaterial;
} }
else if (Appearance.player == "1Tag") else if (Appearance.player == "1Tag")
{ {
if (Appearance.condition == Appearance.Condition.Duel) if (Appearance.condition == Appearance.Condition.Duel)
Appearance.duelProtector1Tag = Protector.material; Appearance.duelProtector1Tag = protectorMaterial;
else if (Appearance.condition == Appearance.Condition.Watch) else if (Appearance.condition == Appearance.Condition.Watch)
Appearance.watchProtector1Tag = Protector.material; Appearance.watchProtector1Tag = protectorMaterial;
else if (Appearance.condition == Appearance.Condition.Replay) else if (Appearance.condition == Appearance.Condition.Replay)
Appearance.replayProtector1Tag = Protector.material; Appearance.replayProtector1Tag = protectorMaterial;
} }
} }
else else
......
...@@ -547,6 +547,7 @@ namespace MDPro3.UI.ServantUI ...@@ -547,6 +547,7 @@ namespace MDPro3.UI.ServantUI
public override void Initialize(Servant.Servant servant) public override void Initialize(Servant.Servant servant)
{ {
base.Initialize(servant); base.Initialize(servant);
ButtonRetry.SetClickEvent(OnRetry);
InitializeVolume(); InitializeVolume();
InitializeScreenMode(); InitializeScreenMode();
...@@ -609,7 +610,10 @@ namespace MDPro3.UI.ServantUI ...@@ -609,7 +610,10 @@ namespace MDPro3.UI.ServantUI
ToggleWatch.gameObject.SetActive(false); ToggleWatch.gameObject.SetActive(false);
ToggleReplay.gameObject.SetActive(false); ToggleReplay.gameObject.SetActive(false);
ButtonRetry.gameObject.SetActive(false); var canRetrySolo = RoomServant.FromSolo;
ButtonRetry.gameObject.SetActive(canRetrySolo);
if (canRetrySolo)
ButtonRetry.SetButtonText(InterString.Get("重试"));
ButtonSurrender.gameObject.SetActive(true); ButtonSurrender.gameObject.SetActive(true);
ButtonSurrender.SetButtonText(InterString.Get("投降")); ButtonSurrender.SetButtonText(InterString.Get("投降"));
} }
...@@ -2387,6 +2391,17 @@ namespace MDPro3.UI.ServantUI ...@@ -2387,6 +2391,17 @@ namespace MDPro3.UI.ServantUI
Program.instance.ocgcore.OnDuelResultConfirmed(true); Program.instance.ocgcore.OnDuelResultConfirmed(true);
} }
public void OnRetry()
{
if (OcgCore.condition != OcgCore.Condition.Duel || !RoomServant.FromSolo)
return;
if (!Program.instance.solo.CanRetryLastSoloDuel())
return;
Program.instance.ocgcore.onSurrenderConfirmed = Program.instance.solo.QueueRetryLastSoloDuel;
Program.instance.ocgcore.OnDuelResultConfirmed(true);
}
} }
public partial class SROptions public partial class SROptions
......
...@@ -410,7 +410,7 @@ namespace MDPro3.UI ...@@ -410,7 +410,7 @@ namespace MDPro3.UI
ParamatorAreaBottom.SetActive(false); ParamatorAreaBottom.SetActive(false);
SpellTrapType.SetActive(true); SpellTrapType.SetActive(true);
IconSpellTrapType.sprite = TextureManager.container.GetCardSpellTrapTypeIcon(data); IconSpellTrapType.sprite = TextureManager.container.GetCardSpellTrapTypeIcon(data);
TextSpellTrapType.text = data.GetSpellTrapType(); TextSpellTrapType.text = data.GetSpellTrapType(true);
PoolGroup.SetParent(ParamatorAreaTop.transform, false); PoolGroup.SetParent(ParamatorAreaTop.transform, false);
} }
......
...@@ -428,7 +428,7 @@ namespace MDPro3.UI ...@@ -428,7 +428,7 @@ namespace MDPro3.UI
{ {
SpellTrapType.SetActive(true); SpellTrapType.SetActive(true);
IconSpellTrapType.sprite = TextureManager.container.GetCardSpellTrapTypeIcon(data); IconSpellTrapType.sprite = TextureManager.container.GetCardSpellTrapTypeIcon(data);
TextSpellTrapType.text = data.GetSpellTrapType(); TextSpellTrapType.text = data.GetSpellTrapType(true);
IconAtk.gameObject.SetActive(false); IconAtk.gameObject.SetActive(false);
IconDef.gameObject.SetActive(false); IconDef.gameObject.SetActive(false);
......
...@@ -7,6 +7,8 @@ namespace YGOSharp ...@@ -7,6 +7,8 @@ namespace YGOSharp
public IList<int> BannedIds { get; private set; } public IList<int> BannedIds { get; private set; }
public IList<int> LimitedIds { get; private set; } public IList<int> LimitedIds { get; private set; }
public IList<int> SemiLimitedIds { get; private set; } public IList<int> SemiLimitedIds { get; private set; }
public IList<int> UnlimitedIds { get; private set; }
public bool WhitelistOnly { get; private set; }
public uint Hash { get; private set; } public uint Hash { get; private set; }
public Banlist() public Banlist()
...@@ -14,6 +16,8 @@ namespace YGOSharp ...@@ -14,6 +16,8 @@ namespace YGOSharp
BannedIds = new List<int>(); BannedIds = new List<int>();
LimitedIds = new List<int>(); LimitedIds = new List<int>();
SemiLimitedIds = new List<int>(); SemiLimitedIds = new List<int>();
UnlimitedIds = new List<int>();
WhitelistOnly = false;
Hash = 0x7dfcee6a; Hash = 0x7dfcee6a;
} }
...@@ -25,12 +29,22 @@ namespace YGOSharp ...@@ -25,12 +29,22 @@ namespace YGOSharp
return 1; return 1;
if (SemiLimitedIds.Contains(cardId)) if (SemiLimitedIds.Contains(cardId))
return 2; return 2;
if (UnlimitedIds.Contains(cardId))
return 3; return 3;
return WhitelistOnly ? 0 : 3;
}
public void EnableWhitelistMode()
{
if (WhitelistOnly)
return;
WhitelistOnly = true;
Hash ^= 0x0f0f0f0f;
} }
public void Add(int cardId, int quantity) public void Add(int cardId, int quantity)
{ {
if (quantity < 0 || quantity > 2) if (quantity < 0 || quantity > 3)
return; return;
switch (quantity) switch (quantity)
{ {
...@@ -43,6 +57,9 @@ namespace YGOSharp ...@@ -43,6 +57,9 @@ namespace YGOSharp
case 2: case 2:
SemiLimitedIds.Add(cardId); SemiLimitedIds.Add(cardId);
break; break;
case 3:
UnlimitedIds.Add(cardId);
break;
} }
uint code = (uint)cardId; uint code = (uint)cardId;
Hash = Hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + quantity)) | (code >> (5 - quantity))); Hash = Hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + quantity)) | (code >> (5 - quantity)));
......
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
namespace YGOSharp namespace YGOSharp
...@@ -25,6 +26,12 @@ namespace YGOSharp ...@@ -25,6 +26,12 @@ namespace YGOSharp
Banlists.Add(current); Banlists.Add(current);
continue; continue;
} }
if (line.StartsWith("$"))
{
if (current != null && line.Equals("$whitelist", StringComparison.OrdinalIgnoreCase))
current.EnableWhitelistMode();
continue;
}
if (!line.Contains(" ")) if (!line.Contains(" "))
continue; continue;
if (current == null) if (current == null)
......
fileFormatVersion: 2
guid: 5b696a850bf3a3443bf0e67396ecc181
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WindowsStoreApps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 9f9e97c267d35b84db512595c857ffba
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WindowsStoreApps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 838190b6b8c45334bab89da28a238150
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WindowsStoreApps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment