From e035806b41091629c41da28ec919f9318b6fedf0 Mon Sep 17 00:00:00 2001 From: Hay1tsme Date: Mon, 13 Nov 2023 17:17:27 -0500 Subject: [PATCH] sao: fix yui shops --- titles/sao/base.py | 98 +++++++++- titles/sao/data/GashaMedalShopItems.csv | 2 +- titles/sao/data/GashaMedalShops.csv | 2 +- titles/sao/data/ResEarnCampaignShopItems.csv | 2 +- titles/sao/data/ResEarnCampaignShops.csv | 2 +- titles/sao/data/YuiMedalShopItems.csv | 2 +- titles/sao/data/YuiMedalShops.csv | 2 +- titles/sao/handlers/base.py | 82 +++++++- titles/sao/handlers/helpers.py | 193 ++++++++++++++++++- 9 files changed, 373 insertions(+), 12 deletions(-) diff --git a/titles/sao/base.py b/titles/sao/base.py index d1b8f96..2470e7e 100644 --- a/titles/sao/base.py +++ b/titles/sao/base.py @@ -1,6 +1,8 @@ import logging from csv import * from random import choice +from typing import Dict, List +from os import path from core.data import Data from core import CoreConfig @@ -17,6 +19,19 @@ class SaoBase: self.version = 0 self.logger = logging.getLogger("sao") + def load_data_csv(self, file: str) -> List[Dict]: + ret = [] + if path.exists(f"titles/sao/data/{file}.csv"): + with open(f"titles/sao/data/{file}.csv", "r", encoding="utf8") as f: + data = csv.DictReader(f, delimiter=',') + for x in data: + ret.append(x) + + return ret + + self.logger.warning(f"Failed to find csv file {file}.csv") + return ret + def handle_noop(self, header: SaoRequestHeader, request: bytes) -> bytes: self.logger.info(f"Using Generic handler") resp_thing = SaoNoopResponse(header.cmd + 1) @@ -835,7 +850,86 @@ class SaoBase: def handle_c700(self, header: SaoRequestHeader, request: bytes) -> bytes: # shop/get_shop_resource_sales_data_list - # TODO: Shop data + # TODO: Get user shop data req = GetShopResourceSalesDataListRequest(header, request) resp = GetShopResourceSalesDataListResponse(header.cmd + 1) - return resp.make() \ No newline at end of file + return resp.make() + + def handle_d100(self, header: SaoRequestHeader, request: bytes) -> bytes: + # shop/get_yui_medal_shop_user_data_list + # TODO: Get user shop data + req = GetYuiMedalShopUserDataListRequest(header, request) + resp = GetYuiMedalShopUserDataListResponse(header.cmd + 1) + return resp.make() + + def handle_cf0e(self, header: SaoRequestHeader, request: bytes) -> bytes: + # gasha/get_gasha_medal_shop_user_data_list + # TODO: Get user shop data + req = GetGashaMedalShopUserDataListRequest(header, request) + resp = GetGashaMedalShopUserDataListResponse(header.cmd + 1) + return resp.make() + + def handle_d5da(self, header: SaoRequestHeader, request: bytes) -> bytes: + # master_data/get_m_yui_medal_shops + req = GetMYuiMedalShopDataRequest(header, request) + resp = GetMYuiMedalShopDataResponse(header.cmd + 1) + + shops = self.load_data_csv("YuiMedalShops") + for shop in shops: + tmp = YuiMedalShopData.from_args(int(shop['YuiMedalShopId']), shop['Name'], shop['Description']) + tmp.selling_yui_medal = int(shop['SellingYuiMedal']) + tmp.selling_col = int(shop['SellingCol']) + tmp.selling_event_item_id = int(shop['SellingEventItemId']) + tmp.selling_event_item_num = int(shop['SellingEventItemNum']) + tmp.selling_ticket_num = int(shop['SellingTicketNum']) + tmp.purchase_limit = int(shop['PurchaseLimit']) + tmp.pick_up_flag = 1 if shop['PickUpFlag'] == "True" else 0 + tmp.product_category = int(shop['ProductCategory']) + tmp.sales_type = int(shop['SalesType']) + tmp.target_days = int(shop['TargetDays']) + tmp.target_hour = int(shop['TargetHour']) + tmp.interval_hour = int(shop['IntervalHour']) + tmp.sort = int(shop['Sort']) + + tmp.sales_end_date = datetime(2100, 1, 1, 0, 0, 0, 0) # always open + + resp.data_list.append(tmp) + + return resp.make() + + def handle_d5dc(self, header: SaoRequestHeader, request: bytes) -> bytes: + # master_data/get_m_yui_medal_shop_items + req = GetMYuiMedalShopItemsRequest(header, request) + resp = GetMYuiMedalShopItemsResponse(header.cmd + 1) + + shops = self.load_data_csv("YuiMedalShopItems") + for shop in shops: + tmp = YuiMedalShopItemData.from_args(int(shop['YuiMedalShopItemId']), int(shop['YuiMedalShopId']), int(shop['CommonRewardType']), int(shop['CommonRewardId']), int(shop['CommonRewardNum']), int(shop['Strength'])) + + tmp.property1_property_id = int(shop['Property1PropertyId']) + tmp.property1_value1 = int(shop['Property1Value1']) + tmp.property1_value2 = int(shop['Property1Value2']) + + tmp.property2_property_id = int(shop['Property2PropertyId']) + tmp.property2_value1 = int(shop['Property2Value1']) + tmp.property2_value2 = int(shop['Property2Value2']) + + tmp.property3_property_id = int(shop['Property3PropertyId']) + tmp.property3_value1 = int(shop['Property3Value1']) + tmp.property3_value2 = int(shop['Property3Value2']) + + tmp.property4_property_id = int(shop['Property4PropertyId']) + tmp.property4_value1 = int(shop['Property4Value1']) + tmp.property4_value2 = int(shop['Property4Value2']) + + resp.data_list.append(tmp) + + return resp.make() + + def handle_d5fc(self, header: SaoRequestHeader, request: bytes) -> bytes: + # master_data/get_m_gasha_medal_shops + pass + + def handle_d604(self, header: SaoRequestHeader, request: bytes) -> bytes: + # master_data_2/get_m_res_earn_campaign_shops + pass \ No newline at end of file diff --git a/titles/sao/data/GashaMedalShopItems.csv b/titles/sao/data/GashaMedalShopItems.csv index 34b4504..c5a46ae 100644 --- a/titles/sao/data/GashaMedalShopItems.csv +++ b/titles/sao/data/GashaMedalShopItems.csv @@ -1,4 +1,4 @@ -// GashaMedalShopItemId,GashaMedalShopId,CommonRewardType,CommonRewardId,CommonRewardNum,Strength,Property1PropertyId,Property1Value1,Property1Value2,Property2PropertyId,Property2Value1,Property2Value2,Property3PropertyId,Property3Value1,Property3Value2,Property4PropertyId,Property4Value1,Property4Value2 +GashaMedalShopItemId,GashaMedalShopId,CommonRewardType,CommonRewardId,CommonRewardNum,Strength,Property1PropertyId,Property1Value1,Property1Value2,Property2PropertyId,Property2Value1,Property2Value2,Property3PropertyId,Property3Value1,Property3Value2,Property4PropertyId,Property4Value1,Property4Value2 15701,15701,1,101000220,1,0,1,0,0,1,0,0,2,0,0,2,0,0 15702,15702,1,102000230,1,0,1,0,0,1,0,0,2,0,0,2,0,0 15703,15703,2,101000009,1,0,204000,5,0,1,0,0,2,0,0,2,0,0 diff --git a/titles/sao/data/GashaMedalShops.csv b/titles/sao/data/GashaMedalShops.csv index 1f0e2e5..a4a78dc 100644 --- a/titles/sao/data/GashaMedalShops.csv +++ b/titles/sao/data/GashaMedalShops.csv @@ -1,4 +1,4 @@ -// GashaMedalShopId,Name,GashaMedalId,UseGashaMedalNum,PurchaseLimit,StartDate,EndDate +GashaMedalShopId,Name,GashaMedalId,UseGashaMedalNum,PurchaseLimit,StartDate,EndDate 15701,"≪不屈の誓い≫キリト",10002,300,-1,"2020/03/10 7:00:00","2020/03/31 2:00:00" 15702,"≪明日への誓い≫アスナ",10002,300,-1,"2020/03/10 7:00:00","2020/03/31 2:00:00" 15703,"ダークリパルサー",10002,60,-1,"2020/03/10 7:00:00","2020/03/31 2:00:00" diff --git a/titles/sao/data/ResEarnCampaignShopItems.csv b/titles/sao/data/ResEarnCampaignShopItems.csv index 83810b6..6d5dd17 100644 --- a/titles/sao/data/ResEarnCampaignShopItems.csv +++ b/titles/sao/data/ResEarnCampaignShopItems.csv @@ -1,4 +1,4 @@ -// ResEarnCampaignShopItemId,ResEarnCampaignShopId,CommonRewardType,CommonRewardId,CommonRewardNum,Strength,Property1PropertyId,Property1Value1,Property1Value2,Property2PropertyId,Property2Value1,Property2Value2,Property3PropertyId,Property3Value1,Property3Value2,Property4PropertyId,Property4Value1,Property4Value2 +ResEarnCampaignShopItemId,ResEarnCampaignShopId,CommonRewardType,CommonRewardId,CommonRewardNum,Strength,Property1PropertyId,Property1Value1,Property1Value2,Property2PropertyId,Property2Value1,Property2Value2,Property3PropertyId,Property3Value1,Property3Value2,Property4PropertyId,Property4Value1,Property4Value2 15701,15701,1,101000220,1,0,1,0,0,1,0,0,2,0,0,2,0,0 15702,15702,1,102000230,1,0,1,0,0,1,0,0,2,0,0,2,0,0 15703,15703,2,101000009,1,0,204000,5,0,1,0,0,2,0,0,2,0,0 diff --git a/titles/sao/data/ResEarnCampaignShops.csv b/titles/sao/data/ResEarnCampaignShops.csv index c52c00d..2c201c9 100644 --- a/titles/sao/data/ResEarnCampaignShops.csv +++ b/titles/sao/data/ResEarnCampaignShops.csv @@ -1,4 +1,4 @@ -// ResEarnCampaignShopId,ResEarnCampaignApplicationId,Name,SellingYuiMedal,SellingCol,SellingEventItemId,SellingEventItemNum,PurchaseLimit,GetApplicationPoint,StartDate,EndDate +ResEarnCampaignShopId,ResEarnCampaignApplicationId,Name,SellingYuiMedal,SellingCol,SellingEventItemId,SellingEventItemNum,PurchaseLimit,GetApplicationPoint,StartDate,EndDate 15701,10001,"≪不屈の誓い≫キリト",-1,1,-1,-1,-1,1,"2020/01/01 7:00:00","2020/03/31 2:00:00" 15702,10001,"≪明日への誓い≫アスナ",-1,12,-1,-1,-1,1,"2020/01/01 7:00:00","2020/03/31 2:00:00" 15703,10001,"ダークリパルサー",-1,123,-1,-1,-1,1,"2020/01/01 7:00:00","2020/03/31 2:00:00" diff --git a/titles/sao/data/YuiMedalShopItems.csv b/titles/sao/data/YuiMedalShopItems.csv index 0ce9157..f5d91fe 100644 --- a/titles/sao/data/YuiMedalShopItems.csv +++ b/titles/sao/data/YuiMedalShopItems.csv @@ -1,4 +1,4 @@ -// YuiMedalShopItemId,YuiMedalShopId,CommonRewardType,CommonRewardId,CommonRewardNum,Strength,Property1PropertyId,Property1Value1,Property1Value2,Property2PropertyId,Property2Value1,Property2Value2,Property3PropertyId,Property3Value1,Property3Value2,Property4PropertyId,Property4Value1,Property4Value2 +YuiMedalShopItemId,YuiMedalShopId,CommonRewardType,CommonRewardId,CommonRewardNum,Strength,Property1PropertyId,Property1Value1,Property1Value2,Property2PropertyId,Property2Value1,Property2Value2,Property3PropertyId,Property3Value1,Property3Value2,Property4PropertyId,Property4Value1,Property4Value2 1,1,1,101000190,1,0,1,0,0,1,0,0,2,0,0,2,0,0 2,2,1,110000150,1,0,1,0,0,1,0,0,2,0,0,2,0,0 3,3,2,120000003,1,0,302000,10,0,301900,20,0,2,0,0,2,0,0 diff --git a/titles/sao/data/YuiMedalShops.csv b/titles/sao/data/YuiMedalShops.csv index 3c0cfb9..5bac235 100644 --- a/titles/sao/data/YuiMedalShops.csv +++ b/titles/sao/data/YuiMedalShops.csv @@ -1,4 +1,4 @@ -// YuiMedalShopId,Name,Description,SellingYuiMedal,SellingCol,SellingEventItemId,SellingEventItemNum,SellingTicketNum,PurchaseLimit,PickUpFlag,ProductCategory,SalesType,TargetDays,TargetHour,IntervalHour,SalesStartDate,SalesEndDate,Sort +YuiMedalShopId,Name,Description,SellingYuiMedal,SellingCol,SellingEventItemId,SellingEventItemNum,SellingTicketNum,PurchaseLimit,PickUpFlag,ProductCategory,SalesType,TargetDays,TargetHour,IntervalHour,SalesStartDate,SalesEndDate,Sort 1,"≪想い馳せる窓辺≫キリト",,5,-1,0,-1,-1,-1,True,0,0,0,0,0,"2019/08/01","2019/11/01 2:00:00",0 2,"≪悪戯なオネーサン≫アルゴ",,5,-1,0,-1,-1,-1,True,0,0,0,0,0,"2019/08/01","2019/11/01 2:00:00",0 3,"ネックレス",,2,-1,0,-1,-1,-1,False,0,0,0,0,0,"2019/08/01","2019/11/01 2:00:00",0 diff --git a/titles/sao/handlers/base.py b/titles/sao/handlers/base.py index bd93fbb..426ca5f 100644 --- a/titles/sao/handlers/base.py +++ b/titles/sao/handlers/base.py @@ -3103,7 +3103,7 @@ class GetShopResourceSalesDataListRequest(SaoBaseRequest): user_id = decode_str(data, off) self.user_id = user_id[0] off += user_id[1] - + class GetShopResourceSalesDataListResponse(SaoBaseResponse): def __init__(self, cmd_id: int) -> None: super().__init__(cmd_id) @@ -3115,4 +3115,82 @@ class GetShopResourceSalesDataListResponse(SaoBaseResponse): ret += encode_arr_cls(self.shop_resource_sales_data) self.header.length = len(ret) - return super().make() + ret \ No newline at end of file + return super().make() + ret + +class GetYuiMedalShopUserDataListRequest(SaoBaseRequest): + def __init__(self, header: SaoRequestHeader, data: bytes) -> None: + super().__init__(header, data) + off = 0 + user_id = decode_str(data, off) + self.user_id = user_id[0] + off += user_id[1] + +class GetYuiMedalShopUserDataListResponse(SaoBaseResponse): + def __init__(self, cmd_id: int) -> None: + super().__init__(cmd_id) + self.result = 1 # byte + self.user_data_list: List[YuiMedalShopUserData] = [] + + def make(self) -> bytes: + ret = encode_byte(self.result) + ret += encode_arr_cls(self.user_data_list) + + self.header.length = len(ret) + return super().make() + ret + +class GetGashaMedalShopUserDataListRequest(SaoBaseRequest): + def __init__(self, header: SaoRequestHeader, data: bytes) -> None: + super().__init__(header, data) + off = 0 + user_id = decode_str(data, off) + self.user_id = user_id[0] + off += user_id[1] + +class GetGashaMedalShopUserDataListResponse(SaoBaseResponse): + def __init__(self, cmd_id: int) -> None: + super().__init__(cmd_id) + self.result = 1 # byte + self.data_list: List[GashaMedalShopUserData] = [] + + def make(self) -> bytes: + ret = encode_byte(self.result) + ret += encode_arr_cls(self.data_list) + + self.header.length = len(ret) + return super().make() + ret + +class GetMYuiMedalShopDataRequest(SaoBaseRequest): + def __init__(self, header: SaoRequestHeader, data: bytes) -> None: + super().__init__(header, data) + self.dummy = decode_byte(data, 0) + +class GetMYuiMedalShopDataResponse(SaoBaseResponse): + def __init__(self, cmd_id: int) -> None: + super().__init__(cmd_id) + self.result = 1 # byte + self.data_list: List[YuiMedalShopData] = [] + + def make(self) -> bytes: + ret = encode_byte(self.result) + ret += encode_arr_cls(self.data_list) + + self.header.length = len(ret) + return super().make() + ret + +class GetMYuiMedalShopItemsRequest(SaoBaseRequest): + def __init__(self, header: SaoRequestHeader, data: bytes) -> None: + super().__init__(header, data) + self.dummy = decode_byte(data, 0) + +class GetMYuiMedalShopItemsResponse(SaoBaseResponse): + def __init__(self, cmd_id: int) -> None: + super().__init__(cmd_id) + self.result = 1 # byte + self.data_list: List[YuiMedalShopItemData] = [] + + def make(self) -> bytes: + ret = encode_byte(self.result) + ret += encode_arr_cls(self.data_list) + + self.header.length = len(ret) + return super().make() + ret diff --git a/titles/sao/handlers/helpers.py b/titles/sao/handlers/helpers.py index 8123a18..9ad26f0 100644 --- a/titles/sao/handlers/helpers.py +++ b/titles/sao/handlers/helpers.py @@ -594,7 +594,7 @@ class ShopResourceSalesData(BaseHelper): self._sz += sales_resource_data_list[1] @classmethod - def from_args(cls, resource_id: str = "0", discharge_id: int = "0", remaining: int = 0, purchased: int = 0) -> "ShopResourceSalesData": + def from_args(cls, resource_id: str = "0", discharge_id: str = "0", remaining: int = 0, purchased: int = 0) -> "ShopResourceSalesData": ret = cls(b"\x00" * 20, 0) ret.user_shop_resource_id = resource_id ret.discharge_user_id = discharge_id @@ -610,4 +610,193 @@ class ShopResourceSalesData(BaseHelper): ret += encode_str(fmt_dt(self.sales_start_date)) ret += encode_arr_cls(self.sales_resource_data_list) return ret - \ No newline at end of file + +class YuiMedalShopUserData(BaseHelper): + def __init__(self, data: bytes, offset: int) -> None: + super().__init__(data, offset) + self.yui_medal_shop_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + self.purchase_num = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + last_purchase_date = decode_str(data, offset + self._sz) + self.last_purchase_date = last_purchase_date[0] + self._sz += last_purchase_date[1] + + @classmethod + def from_args(cls, yui_medal_shop_id: int = 0, purchase_num: int = 0, last_purchase_date: datetime = datetime.fromtimestamp(0)) -> "YuiMedalShopUserData": + ret = cls(b"\x00" * 20, 0) + ret.yui_medal_shop_id = yui_medal_shop_id + ret.purchase_num = purchase_num + ret.last_purchase_date = last_purchase_date + + def make(self) -> bytes: + ret = encode_int(self.yui_medal_shop_id) + ret += encode_int(self.purchase_num) + ret += encode_str(fmt_dt(self.last_purchase_date)) + return ret + +class GashaMedalShopUserData(BaseHelper): + def __init__(self, data: bytes, offset: int) -> None: + super().__init__(data, offset) + self.gasha_medal_shop_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + self.purchase_num = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + @classmethod + def from_args(cls, gasha_medal_shop_id: int = 0, purchase_num: int = 0) -> "GashaMedalShopUserData": + ret = cls(b"\x00" * 20, 0) + ret.gasha_medal_shop_id = gasha_medal_shop_id + ret.purchase_num = purchase_num + + def make(self) -> bytes: + ret = encode_int(self.gasha_medal_shop_id) + ret += encode_int(self.purchase_num) + return ret + +class YuiMedalShopData(BaseHelper): + def __init__(self, data: bytes, offset: int) -> None: + super().__init__(data, offset) + self.yui_medal_shop_id = decode_int(data, offset + self._sz) + + name = decode_str(data, offset + self._sz) + self.name = name[0] + self._sz += name[1] + + description = decode_str(data, offset + self._sz) + self.description = description[0] + self._sz += description[1] + + self.selling_yui_medal = decode_short(data, offset + self._sz) + self.selling_col = decode_int(data, offset + self._sz) + self.selling_event_item_id = decode_int(data, offset + self._sz) + self.selling_event_item_num = decode_int(data, offset + self._sz) + self.selling_ticket_num = decode_int(data, offset + self._sz) + self.purchase_limit = decode_short(data, offset + self._sz) + self.pick_up_flag = decode_byte(data, offset + self._sz) + self.product_category = decode_byte(data, offset + self._sz) + self.sales_type = decode_byte(data, offset + self._sz) + self.target_days = decode_byte(data, offset + self._sz) + self.target_hour = decode_byte(data, offset + self._sz) + self.interval_hour = decode_byte(data, offset + self._sz) + + sales_start_date = decode_str(data, offset + self._sz) + self.sales_start_date = prs_dt(sales_start_date[0]) + self._sz += sales_start_date[1] + + sales_end_date = decode_str(data, offset + self._sz) + self.sales_end_date = prs_dt(sales_end_date[0]) + self._sz += sales_end_date[1] + + self.sort = decode_byte(data, offset + self._sz) + + @classmethod + def from_args(cls, shop_id: int = 0, name: str = "", desc: str = "") -> "YuiMedalShopData": + ret = cls(b"\x00" * 43, 0) + ret.yui_medal_shop_id = shop_id + ret.name = name + ret.description = desc + + def make(self) -> bytes: + ret = encode_int(self.yui_medal_shop_id) + ret += encode_str(self.name) + ret += encode_str(self.description) + ret += encode_short(self.selling_yui_medal) + ret += encode_int(self.selling_col) + ret += encode_int(self.selling_event_item_id) + ret += encode_int(self.selling_event_item_num) + ret += encode_int(self.selling_ticket_num) + ret += encode_short(self.purchase_limit) + ret += encode_byte(self.pick_up_flag) + ret += encode_byte(self.product_category) + ret += encode_byte(self.sales_type) + ret += encode_byte(self.target_days) + ret += encode_byte(self.target_hour) + ret += encode_byte(self.interval_hour) + ret += encode_str(self.sales_end_date) + ret += encode_str(self.sales_end_date) + ret += encode_byte(self.sort) + return ret + +class YuiMedalShopItemData(BaseHelper): + def __init__(self, data: bytes, offset: int) -> None: + super().__init__(data, offset) + self.yui_medal_shop_item_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.yui_medal_shop_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.common_reward_type = decode_byte(data, offset + self._sz) + self._sz += BYTE_OFF + self.common_reward_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.common_reward_num = decode_short(data, offset + self._sz) + self._sz += SHORT_OFF + self.strength = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + self.property1_property_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.property1_value1 = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.property1_value2 = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + self.property2_property_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.property2_value1 = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.property2_value2 = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + self.property3_property_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.property3_value1 = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.property3_value2 = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + self.property4_property_id = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.property4_value1 = decode_int(data, offset + self._sz) + self._sz += INT_OFF + self.property4_value2 = decode_int(data, offset + self._sz) + self._sz += INT_OFF + + @classmethod + def from_args(cls, item_id: int = 0, shop_id: int = 0, reward_type: int = 0, reward_id: int = 0, reward_num: int = 0, strength: int = 0) -> "YuiMedalShopItemData": + ret = cls(b"\x00" * 67, 0) + ret.yui_medal_shop_item_id = item_id + ret.yui_medal_shop_id = shop_id + ret.common_reward_type = reward_type + ret.common_reward_id = reward_id + ret.common_reward_num = reward_num + ret.strength = strength + return ret + + def make(self) -> bytes: + ret = encode_int(self.yui_medal_shop_item_id) + ret += encode_int(self.yui_medal_shop_id) + ret += encode_byte(self.common_reward_type) + ret += encode_int(self.common_reward_id) + ret += encode_short(self.common_reward_num) + ret += encode_int(self.strength) + + ret += encode_int(self.property1_property_id) + ret += encode_int(self.property1_value1) + ret += encode_int(self.property1_value2) + + ret += encode_int(self.property2_property_id) + ret += encode_int(self.property2_value1) + ret += encode_int(self.property2_value2) + + ret += encode_int(self.property3_property_id) + ret += encode_int(self.property3_value1) + ret += encode_int(self.property3_value2) + + ret += encode_int(self.property4_property_id) + ret += encode_int(self.property4_value1) + ret += encode_int(self.property4_value2) + return ret