local XRestaurantStaff = require("XModule/XRestaurant/XRestaurantStaff") local XIngredient = require("XModule/XRestaurant/XProduct/XIngredient") local XFood = require("XModule/XRestaurant/XProduct/XFood") local XCashier = require("XModule/XRestaurant/XProduct/XCashier") local XCookingWorkBench = require("XModule/XRestaurant/XWorkBench/XCookingWorkBench") local XIngredientWorkBench = require("XModule/XRestaurant/XWorkBench/XIngredientWorkBench") local XSalesWorkBench = require("XModule/XRestaurant/XWorkBench/XSalesWorkBench") local XRestaurantOrder = require("XModule/XRestaurant/XRestaurantOrder") local XRestaurantBuff = require("XModule/XRestaurant/XBuff/XRestaurantBuff") local SimulationTimer local SimulationDelay = XScheduleManager.SECOND local LastSimulationTime = 0 local LuaMemoryLimit = 500 * 1024 --进入餐厅增加500M后会GC一次 ---@class XRestaurant : XDataEntityBase 战双厨房玩法活动数据对象 ---@field private _Id number 活动Id ---@field private _Level number 餐厅等级 ---@field private _IsLevelUp boolean 餐厅是否升级 ---@field private _CookingWorkBenches XCookingWorkBench[] 已解锁烹饪台 ---@field private _IngredientWorkBenches XIngredientWorkBench[] 已解备菜台 ---@field private _SalesWorkBenches XSalesWorkBench[] 已解锁售卖台 ---@field private _StaffMap table 员工列表 ---@field private _FoodMap table 食物列表 ---@field private _IngredientMap table 食材列表 ---@field private _Cashier XCashier 收银台 ---@field private _OfflineBill number 离线账单 ---@field private _OfflineBillUpdateTime number 上次离开餐厅时间 ---@field private _CurDay number 活动开放天数 ---@field private _AccelerateUseTimes number 当天加速道具使用次数 ---@field private _IsGetSignReward boolean 是否领取签到奖励 ---@field private _EventLevelConditionChange number 升级所需条件改变事件 ---@field private _UnlockIngredient table 已解锁食材 ---@field private _UnlockFood table 已解锁食物 ---@field private _EnterRoomMemory number 进入餐厅时的Lua内存 ---@field private _OrderInfo XRestaurantOrder 订单数据 ---@field private _BuffMap table 已经解锁Buff ---@field private _AreaTypeBuff table 每个区域对应的BuffId ---@field private _AreaSortMark table 每个区域工作台排序标记 local XRestaurant = XClass(XDataEntityBase, "XRestaurant") local default = { _Id = 0, --活动Id, _Level = 0, _IsLevelUp = false, _CookingWorkBenches = {}, _IngredientWorkBenches = {}, _SalesWorkBenches = {}, _StaffMap = {}, _FoodMap = {}, _IngredientMap = {}, _Cashier = nil, _UnlockIngredient = {}, _UnlockFood = {}, _OfflineBill = 0, _OfflineBillUpdateTime = 0, _CurDay = 0, _AccelerateUseTimes = 0, _IsGetSignReward = false, _EventLevelConditionChange = 0, _OrderInfo = nil, _AreaTypeBuff = {}, _BuffMap = {}, _AreaSortMark = {}, _BuffRedPointMarkCount = 0, _MenuRedPointMarkCount = 0, _EnterRoomMemory = 0, _UiMainSorting = -1, } function XRestaurant:Ctor(id) self:Init(default, id) end --- 初始化持久数据 ---@private ---@param id number 活动Id ---@return nil -------------------------- function XRestaurant:InitData(id) self:SetProperty("_Id", id) self:_InitStaffList() self:_InitProductList() self._Cashier = XCashier.New() end --- 获取商店Id ---@return number 商店Id -------------------------- function XRestaurant:GetShopId() return XRestaurantConfigs.GetShopId(self._Id) end --- 活动名 ---@return string 活动名 -------------------------- function XRestaurant:GetActivityName() return XRestaurantConfigs.GetActivityName(self._Id) end --- 获取结束时间 ---@return number 结束时间 -------------------------- function XRestaurant:GetBusinessEndTime() return XRestaurantConfigs.GetActivityEndTime(self._Id) end --- 获取开始时间 ---@return number 开始时间 -------------------------- function XRestaurant:GetBusinessStartTime() return XRestaurantConfigs.GetActivityStartTime(self._Id) end function XRestaurant:GetShopStartTime() return XRestaurantConfigs.GetShopStartTime(self._Id) end function XRestaurant:GetShopEndTime() return XRestaurantConfigs.GetShopEndTime(self._Id) end --- 获取任务组列表 ---@return number[] 任务组Id列表 -------------------------- function XRestaurant:GetTimeLimitTaskIds() return XRestaurantConfigs.GetTimeLimitTaskIds(self._Id) end -- 食谱任务 function XRestaurant:GetRecipeTaskId() return XRestaurantConfigs.GetRecipeTaskId(self._Id) end --- 活动是否开启 ---@return boolean 是否开启 -------------------------- function XRestaurant:IsOpen() if not XTool.IsNumberValid(self._Id) then return false end return self:IsInBusiness() or self:IsShopOpen() end --- 餐厅是否营业中 ---@return boolean -------------------------- function XRestaurant:IsInBusiness() return XRestaurantConfigs.CheckActivityInTime(self._Id) end --- 商店是否开放中 ---@return boolean -------------------------- function XRestaurant:IsShopOpen() return XRestaurantConfigs.CheckShopInTime(self._Id) end --- 活动账单结算时间 ---@return number -------------------------- function XRestaurant:GetOfflineBillTime() return XRestaurantConfigs.GetActivityOfflineBillTime(self._Id) end --- 是否展示离线账单 ---@return boolean -------------------------- function XRestaurant:IsShowOfflineBill() if self:IsFirstEnterRoom() then return false end local nowTime = XTime.GetServerNowTimestamp() local billTime = self:GetOfflineBillTime() if nowTime - self._OfflineBillUpdateTime < billTime then return false end return true end --- 首次进入餐厅 ---@return boolean -------------------------- function XRestaurant:IsFirstEnterRoom() return not XTool.IsNumberValid(self._OfflineBillUpdateTime) end function XRestaurant:GetAccelerateUseLimit() return XRestaurantConfigs.GetActivityAccelerateUseLimit(self._Id) end function XRestaurant:GetAccelerateTime() return XRestaurantConfigs.GetActivityAccelerateTime(self._Id) end function XRestaurant:GetAccelerateCount() return XDataCenter.ItemManager.GetCount(XRestaurantConfigs.ItemId.RestaurantAccelerate) end function XRestaurant:IsAccelerateUpperLimit() return self._AccelerateUseTimes >= self:GetAccelerateUseLimit() end function XRestaurant:GetUrgentTime() return XRestaurantConfigs.GetActivityUrgentTime(self._Id) end --- 餐厅升级 ---@param level number 升级后的等级 ---@return void -------------------------- function XRestaurant:LevelUp(level) level = math.max(XRestaurantConfigs.LevelRange.Min, level) local oldLevel = self._Level if level == oldLevel then return end self:SetProperty("_Level", level) self._UnlockIngredient = XRestaurantConfigs.GetUnlockProduct(level, XRestaurantConfigs.GetUnlockIngredient) self._UnlockFood = XRestaurantConfigs.GetUnlockProduct(level, XRestaurantConfigs.GetUnlockFood) self:_InitWorkBench() -- 先更新食材 for _, ingredient in pairs(self._IngredientMap) do ingredient:OnRestaurantLevelUp(level) end -- 再更新食物 for _, food in pairs(self._FoodMap) do food:OnRestaurantLevelUp(level) end self._Cashier:OnRestaurantLevelUp(level) if oldLevel ~= 0 and level > oldLevel then self:SetProperty("_IsLevelUp", true) end end --全部工作台停止工作 function XRestaurant:StopAll() for _, bench in pairs(self._IngredientWorkBenches) do bench:Stop() end for _, bench in pairs(self._CookingWorkBenches) do bench:Stop() end for _, bench in pairs(self._SalesWorkBenches) do bench:Stop() end end --- 更新员工信息 ---@param staffList Server.XRestaurantCharacter[] 员工信息 ---@return void -------------------------- function XRestaurant:UpdateStaffInfo(staffList) for _, info in ipairs(staffList or {}) do local charId = info.CharacterId local staff = self._StaffMap[charId] if not staff then XLog.Warning("XRestaurant:UpdateStaffInfo: not found staff!!! staff Id = " .. tostring(charId)) goto continue end staff:UpdateInfo(true, info.CharacterLv) ::continue:: end end --- 更新仓库 ---@param storageInfo Server.XRestaurantStorage ---@return void -------------------------- function XRestaurant:UpdateStorageInfo(storageInfo) if not storageInfo then return end for _, info in ipairs(storageInfo or {}) do local areaType = info.SectionType local id = info.ProductId if XRestaurantConfigs.CheckIsIngredientArea(areaType) then local ingredient = self._IngredientMap[id] if not ingredient then ingredient = XIngredient.New(id) self._IngredientMap[id] = ingredient end ingredient:SetProperty("_Count", info.Count) elseif XRestaurantConfigs.CheckIsFoodArea(areaType) then local food = self._FoodMap[id] if not food then food = XFood.New(id) self._FoodMap[id] = food end food:SetProperty("_Count", info.Count) elseif XRestaurantConfigs.CheckIsSaleArea(areaType) then self._Cashier:SetProperty("_Count", info.Count) end end end --- 更新工作台状态 ---@param sectionInfos Server.XRestaurantSection[] ---@return void -------------------------- function XRestaurant:UpdateWorkBench(sectionInfos) if not sectionInfos then return end for _, info in ipairs(sectionInfos or {}) do local areaType = info.SectionType local index = info.Index local list = self._AreaMap2Benches[areaType] if not XTool.IsTableEmpty(list) then local bench = list[index] bench:OnNotify(info) end end end --- 更新结算 ---@param offlineBill number 离线账单 ---@param offlineBillUpdateTime number 上次离开餐厅时间 -------------------------- function XRestaurant:UpdateSettle(offlineBill, offlineBillUpdateTime) self:SetProperty("_OfflineBill", offlineBill) self:SetProperty("_OfflineBillUpdateTime", offlineBillUpdateTime) end --- 更新热销 ---@param currentDay number 当前活动天数 ---@return void -------------------------- function XRestaurant:UpdateHotSale(currentDay) self:SetProperty("_CurDay", currentDay or 1) for _, food in pairs(self._FoodMap or {}) do food:UpdateHotSale(false, 0) end local list = XRestaurantConfigs.GetHotSaleDataList(self._CurDay) for _, info in pairs(list or {}) do local id = info.Id if XTool.IsNumberValid(id) then local food = self._FoodMap[id] food:UpdateHotSale(true, info.Addition) end end end function XRestaurant:UpdateSignData(isGetSignReward, signActivityId) self:SetProperty("_IsGetSignReward", isGetSignReward) if XTool.IsNumberValid(signActivityId) then self:SetProperty("_SignActivityId", signActivityId) end end function XRestaurant:UpdateOrderInfo(orderActivityId, orderInfos) if not self._OrderInfo or self._OrderInfo:GetId() ~= orderActivityId then self._OrderInfo = XRestaurantOrder.New(self._Id) end self._OrderInfo:UpdateData(orderInfos) end function XRestaurant:UpdateBuff(areaTypeBuffInfo, unlockBuffs, defaultBuffs) local map = {} for _, info in ipairs(areaTypeBuffInfo) do map[info.SectionType] = info.BuffId end --TODO CodeMoon, 不知道这里需不需要 for _, id in ipairs(defaultBuffs) do local sectionType = XRestaurantConfigs.GetBuffAreaType(id) if not map[sectionType] then map[sectionType] = id end end self:SetProperty("_AreaTypeBuff", map) unlockBuffs = appendArray(unlockBuffs, defaultBuffs) for _, id in ipairs(unlockBuffs) do local buff = self._BuffMap[id] if not buff then buff = XRestaurantBuff.New(id) self._BuffMap[id] = buff end buff:Unlock() end end function XRestaurant:OnNotify(notifyData) self:SetProperty("_AccelerateUseTimes", notifyData.AccelerateUseTimes) --初始化/更新 员工数据 self:UpdateStaffInfo(notifyData.CharacterList) --初始化/更新 产品信息 self:UpdateStorageInfo(notifyData.StorageInfos) --更新餐厅等级 self:LevelUp(notifyData.RestaurantLv) --更新Buff信息 self:UpdateBuff(notifyData.SectionBuffInfos, notifyData.UnlockSectionBuffs, notifyData.DefaultBuffs) --更新订单信息 self:UpdateOrderInfo(notifyData.OrderActivityId, notifyData.OrderInfos) --更新热销 self:UpdateHotSale(notifyData.CurDay) --更新工作台信息 self:UpdateWorkBench(notifyData.SectionInfos) --更新结算 self:UpdateSettle(notifyData.OfflineBill, notifyData.LastSettleTime) --更新签到信息 self:UpdateSignData(notifyData.IsGetSignReward, notifyData.SignActivityId) end function XRestaurant:UpdateLuaMemory() local memory = CS.XLuaEngine.Env.Memroy self:SetProperty("_EnterRoomMemory", memory) end --region ------------------getter and setter start------------------- --- 获取所有产品,包括数量为0以及未解锁 ---@param areaType number ---@return XRestaurantProduct[] -------------------------- function XRestaurant:GetAllProductList(areaType) local map = {} if XRestaurantConfigs.CheckIsIngredientArea(areaType) then map = self._IngredientMap else map = self._FoodMap end local list = {} for _, product in pairs(map or {}) do if product then table.insert(list, product) end end return list end --- 获取所有存货数量大于0产品 ---@param areaType number ---@return XRestaurantProduct[] -------------------------- function XRestaurant:GetNotZeroProductList(areaType) local map = {} if XRestaurantConfigs.CheckIsIngredientArea(areaType) then map = self._IngredientMap else map = self._FoodMap end local list = {} for _, product in pairs(map or {}) do if product and product:GetProperty("_Count") > 0 then table.insert(list, product) end end return list end --- 获取所有已解锁产品列表 ---@param areaType number ---@return XRestaurantProduct[] -------------------------- function XRestaurant:GetUnlockProductList(areaType) local map = {} if XRestaurantConfigs.CheckIsIngredientArea(areaType) then map = self._IngredientMap else map = self._FoodMap end local list = {} for _, product in pairs(map or {}) do if product and product:IsUnlock() then table.insert(list, product) end end return list end --- 已解锁产品个数 ---@param areaType number ---@return number -------------------------- function XRestaurant:GetUnlockProductCount(areaType) local count = 0 local map = {} if XRestaurantConfigs.CheckIsIngredientArea(areaType) then map = self._IngredientMap else map = self._FoodMap end for _, product in pairs(map or {}) do if product and product:IsUnlock() then count = count + 1 end end return count end --- 仓库产品列表 ---@param areaType number ---@return XRestaurantProduct[] -------------------------- function XRestaurant:GetSortStorageProductList(areaType) local list = self:GetUnlockProductList(areaType) if XTool.IsTableEmpty(list) then return list end local isSortByQuality = not XRestaurantConfigs.CheckIsIngredientArea(areaType) table.sort(list, function(a, b) if isSortByQuality then local qualityA = a:GetProperty("_Quality") local qualityB = b:GetProperty("_Quality") if qualityA ~= qualityB then return qualityA > qualityB end end return a:GetProperty("_Id") < b:GetProperty("_Id") end) return list end --- 获取产品 ---@param areaType number ---@param id number ---@return XRestaurantProduct -------------------------- function XRestaurant:GetProduct(areaType, id) local map = {} if XRestaurantConfigs.CheckIsIngredientArea(areaType) then map = self._IngredientMap else map = self._FoodMap end local product = map[id] if not product then XLog.Error("XRestaurant:GetProduct: not found product area type = " .. tostring(areaType) .. " Id = " .. tostring(id)) return {} end return product end --- 获取已解锁留言信息 ---@return XRestaurantOrderInfo[] -------------------------- function XRestaurant:GetUnlockOrderInfoList() if not self._OrderInfo then return {} end return self._OrderInfo:GetUnlockInfoList() end --- 员工列表 ---@return XRestaurantStaff[] -------------------------- function XRestaurant:GetStaffList(areaType) local list = {} for _, staff in pairs(self._StaffMap or {}) do if areaType == 0 or staff:IsAdditionByAreaTypeWithMaxLevel(areaType) then table.insert(list, staff) end end return list end --- 已招募员工 ---@return XRestaurantStaff[] function XRestaurant:GetRecruitStaffList() ---@type XRestaurantStaff[] local list = {} for _, staff in pairs(self._StaffMap or {}) do local recruit = staff:GetProperty("_IsRecruit") if recruit then table.insert(list, staff) end end return list end --- 空闲员工 ---@return XRestaurantStaff[] -------------------------- function XRestaurant:GetFreeStaffList() local list = {} for _, staff in pairs(self._StaffMap or {}) do if staff:GetProperty("_IsRecruit") and not staff:IsWorking() then table.insert(list, staff) end end return list end --- 空闲人数 ---@return number -------------------------- function XRestaurant:GetFreeStaffCount() local count = 0 for _, staff in pairs(self._StaffMap or {}) do if staff:GetProperty("_IsRecruit") and not staff:IsWorking() then count = count + 1 end end return count end --- 在工作台上的人数 ---@return number -------------------------- function XRestaurant:GetOnBenchStaffCount() local count = 0 for _, staff in pairs(self._StaffMap or {}) do if staff:GetProperty("_IsRecruit") and not staff:IsFree() then count = count + 1 end end return count end --- 获取大于等级当前等级的员工 ---@param level number ---@return XRestaurantStaff[] -------------------------- function XRestaurant:GetStaffListByMinLevel(level) ---@type XRestaurantStaff[] local list = {} for _, staff in pairs(self._StaffMap or {}) do local recruit = staff:GetProperty("_IsRecruit") local lv = staff:GetProperty("_Level") if recruit and lv >= level then table.insert(list, staff) end end return list end --- 已招募员工并排序 ---@return XRestaurantStaff[] function XRestaurant:GetSortRecruitStaffList(areaType, productId) ---@type XRestaurantStaff[] local list = self:GetRecruitStaffList() local buff = self:GetAreaBuff(areaType) table.sort(list, function(a, b) local isWorkingA = not a:IsFree() local isWorkingB = not b:IsFree() if isWorkingA ~= isWorkingB then return isWorkingB end local idA = a:GetProperty("_Id") local idB = b:GetProperty("_Id") local buffAdditionA = buff and buff:GetEffectAddition(areaType, a:GetProperty("_Id"), productId) or 0 local buffAdditionB = buff and buff:GetEffectAddition(areaType, b:GetProperty("_Id"), productId) or 0 local additionA = a:GetSkillAddition(areaType, productId) local additionB = b:GetSkillAddition(areaType, productId) local totalA = buffAdditionA + additionA local totalB = buffAdditionB + additionB if totalA ~= totalB then return totalA > totalB end if additionA ~= additionB then return additionA > additionB end if buffAdditionA ~= buffAdditionB then return buffAdditionA > buffAdditionB end local levelA = a:GetProperty("_Level") local levelB = b:GetProperty("_Level") if levelA ~= levelB then return levelA > levelB end return idA < idB end) return list end --- 员工视图数据 ---@param characterId number 员工Id ---@return XRestaurantStaff -------------------------- function XRestaurant:GetStaffViewModel(characterId) local staff = self._StaffMap[characterId] if not staff then XLog.Error("XRestaurant:UpdateStaffInfo: not found staff!!! staff Id = " .. tostring(characterId)) return {} end return staff end --- 获取当前区域正在工作的员工列表 ---@param areaType number ---@return XRestaurantStaff[] -------------------------- function XRestaurant:GetWorkingStaff(areaType) local map if XRestaurantConfigs.CheckIsIngredientArea(areaType) then map = self._IngredientWorkBenches elseif XRestaurantConfigs.CheckIsFoodArea(areaType) then map = self._CookingWorkBenches elseif XRestaurantConfigs.CheckIsSaleArea(areaType) then map = self._SalesWorkBenches end if not map then return {} end local list = {} for _, bench in pairs(map) do if not bench:IsFree() then table.insert(list, bench:GetCharacter()) end end return list end --- 获取工作台视图数据 ---@param areaType number ---@param index number ---@return XRestaurantWorkBench -------------------------- function XRestaurant:GetWorkBenchViewModel(areaType, index, ignoreTip) local list = self._AreaMap2Benches[areaType] if not list then XLog.Error("XRestaurant:GetWorkBenchViewModel: not found work bench area type = " .. tostring(areaType)) return {} end local bench = list[index] if not bench and not ignoreTip then XLog.Error("XRestaurant:GetWorkBenchViewModel: not found work bench area type = " .. tostring(areaType) .. " Index = " .. tostring(index)) return {} end return bench end function XRestaurant:GetUnlockWorkBenchList(areaType) return self._AreaMap2Benches[areaType] end function XRestaurant:CheckFoodUnlock(id) return self._UnlockFood[id] and true or false end function XRestaurant:CheckIngredientUnlock(id) return self._UnlockIngredient[id] and true or false end function XRestaurant:IsUrgentProduct(areaType, id) if not XRestaurantConfigs.CheckIsIngredientArea(areaType) then return false end local produceSpeed = self:GetProduceTotalSpeed(areaType, id) local consumeSpeed = self:GetConsumeTotalSpeed(areaType, id) --未生产,未消耗 if produceSpeed == 0 and consumeSpeed == 0 then return false end --生产速度大于等于消耗速度 if produceSpeed >= consumeSpeed then return false end local urgentTime = self:GetUrgentTime() local product = self:GetProduct(areaType, id) local count = product:GetProperty("_Count") local second = (count / (consumeSpeed - produceSpeed)) * 3600 return second <= urgentTime end --- 获取产品的生产总速 ---@param areaType number 产品类型 ---@param productId number ---@param timeUnit number ---@return number -------------------------- function XRestaurant:GetProduceTotalSpeed(areaType, productId, timeUnit) if not XTool.IsNumberValid(productId) then return 0 end timeUnit = timeUnit or XRestaurantConfigs.TimeUnit.Hour if XRestaurantConfigs.CheckIsIngredientArea(areaType) then return self:_GetIngredientProduceTotalSpeed(productId, timeUnit) elseif XRestaurantConfigs.CheckIsFoodArea(areaType) then return self:_GetFoodProduceTotalSpeed(productId, timeUnit) elseif XRestaurantConfigs.CheckIsSaleArea(areaType) then return self:_GetSaleProduceTotalSpeed(productId, timeUnit) end return 0 end --- 获取产品的消耗总体速度 ---@param areaType number 产品类型 ---@param productId number ---@param timeUnit number ---@return number -------------------------- function XRestaurant:GetConsumeTotalSpeed(areaType, productId, timeUnit) if not XTool.IsNumberValid(productId) then return 0 end timeUnit = timeUnit or XRestaurantConfigs.TimeUnit.Hour if XRestaurantConfigs.CheckIsIngredientArea(areaType) then return self:_GetIngredientConsumeTotalSpeed(productId, timeUnit) elseif XRestaurantConfigs.CheckIsFoodArea(areaType) then return self:_GetFoodConsumeTotalSpeed(productId, timeUnit) elseif XRestaurantConfigs.CheckIsSaleArea(areaType) then return self:_GetSaleConsumeTotalSpeed(productId, timeUnit) end return 0 end function XRestaurant:GetWorkBenchPreviewTip(areaType, productId, timeUnit) local produce = self:GetProduceTotalSpeed(areaType, productId, timeUnit) local consume = self:GetConsumeTotalSpeed(areaType, productId, timeUnit) if produce == 0 and consume == 0 then return true, "" end local product = self:GetProduct(areaType, productId) local subSpeed = produce - consume local freeCount = subSpeed > 0 and product:GetFreeCapacity() or product:GetProperty("_Count") if XRestaurantConfigs.CheckIsIngredientArea(areaType) then return subSpeed > 0, XRestaurantConfigs.GetIngredientStoragePreviewTip(produce, consume, freeCount) elseif XRestaurantConfigs.CheckIsFoodArea(areaType) then --消耗完毕或者满仓速度 local stop = freeCount / math.abs(produce - consume) if not product then return stop end local list = product:GetProperty("_Ingredients") or {} local cStop = stop for _, consume in pairs(list) do local ingredientId = consume:GetId() local ingredient = self:GetProduct(XRestaurantConfigs.AreaType.IngredientArea, ingredientId) local cSpeed = ingredient:GetProperty("_Count") / self:_GetIngredientConsumeTotalSpeed(ingredientId, timeUnit) cStop = math.min(cStop, cSpeed) end local increase = subSpeed > 0 and stop <= cStop local isZero = cStop <= XRestaurantConfigs.Inaccurate and math.abs(subSpeed) <= XRestaurantConfigs.Inaccurate return increase, XRestaurantConfigs.GetCookStoragePreviewTip(increase, stop > cStop, isZero, cStop) elseif XRestaurantConfigs.CheckIsSaleArea(areaType) then local price = self:GetCashierTotalPrice(timeUnit) freeCount = self._Cashier:GetFreeCapacity() --收银台满 local fullTime = freeCount / price --售卖完毕 local consumeTime = product:GetProperty("_Count") / consume return fullTime < consumeTime, XRestaurantConfigs.GetSaleStoragePreviewTip(fullTime, consumeTime) end end --- 收银台总收益 ---@param timeUnit number 单位时间,默认小时 ---@return number -------------------------- function XRestaurant:GetCashierTotalPrice(timeUnit) local price = 0 for _, bench in pairs(self._SalesWorkBenches or {}) do local state = bench:GetProperty("_State") if state == XRestaurantConfigs.WorkState.Free then goto continue end price = price + bench:GetFoodFinalPrice(timeUnit) ::continue:: end return math.ceil(price) end --- 获取签到开始时间 ---@return number|nil -------------------------- function XRestaurant:GetSignActivityStartTime() return XRestaurantConfigs.GetSignActivityStartTime(self._Id) end --- 获取签到结束时间 ---@return number -------------------------- function XRestaurant:GetSignActivityEndTime() return XRestaurantConfigs.GetSignActivityEndTime(self._Id) end --- 判断是否在签到时间内 ---@param defaultOpen boolean ---@return boolean -------------------------- function XRestaurant:CheckSignActivityInTime(defaultOpen) return XRestaurantConfigs.CheckSignActivityInTime(self._Id, defaultOpen) end --- 获取签到活动名称 ---@return number -------------------------- function XRestaurant:GetSignActivityName() return XRestaurantConfigs.GetSignActivityName(self._Id) end --- 获取今天是否能进行签到 ---@return boolean -------------------------- function XRestaurant:GetIsGetSignReward() return self._IsGetSignReward end --- 获取第X天签到的npcId ---@return number function XRestaurant:GetSignCurDay() if not self:CheckSignActivityInTime(false) then return 0 end local day = XTime.GetDayCountUntilTime(XRestaurantConfigs.GetSignActivityStartTime(self._Id), true) return day + 1 end --- 获取第X天签到的奖励 ---@return number -------------------------- function XRestaurant:GetSignActivityRewardId() return XRestaurantConfigs.GetSignActivityRewardId(self._Id, self:GetSignCurDay()) end --- 获取第X天签到的npc立绘Url ---@return string -------------------------- function XRestaurant:GetSignActivityNpcImgUrl() return XRestaurantConfigs.GetSignActivityNpcImgUrl(self._Id, self:GetSignCurDay()) end --- 获取第X天签到的奖励 ---@return string -------------------------- function XRestaurant:GetSignActivitySignDesc() return XUiHelper.ConvertLineBreakSymbol(XRestaurantConfigs.GetSignActivitySignDesc(self._Id, self:GetSignCurDay())) end --- 获取第X天签到的回复文本 ---@return string -------------------------- function XRestaurant:GetSignActivityReplyBtnDesc() return XRestaurantConfigs.GetSignActivityReplyBtnDesc(self._Id, self:GetSignCurDay()) end --- 获取当前订单信息 ---@return XRestaurantOrderInfo -------------------------- function XRestaurant:GetTodayOrderInfo() if not self._OrderInfo then return end return self._OrderInfo:GetTodayOrderInfo() end function XRestaurant:CheckOrderFinish() local orderInfo = self:GetTodayOrderInfo() if not orderInfo then return false end local infos = XRestaurantConfigs.GetOrderFoodInfos(orderInfo:GetId()) local finish = true for _, info in ipairs(infos) do local food = self:GetProduct(XRestaurantConfigs.AreaType.FoodArea, info.Id) local hasCount = food and food:GetProperty("_Count") or 0 if hasCount < info.Count then finish = false break end end return finish end function XRestaurant:GetOrderActivityId() if not self._OrderInfo then return 0 end return self._OrderInfo:GetId() end function XRestaurant:GetBuff(buffId) local buff = self._BuffMap[buffId] if not buff then buff = XRestaurantBuff.New(buffId) self._BuffMap[buffId] = buff end return buff end function XRestaurant:GetAreaBuffId(areaType) if not areaType then return end return self._AreaTypeBuff[areaType] end function XRestaurant:GetAreaBuff(areaType) local buffId = self:GetAreaBuffId(areaType) if not XTool.IsNumberValid(buffId) then return end return self:GetBuff(buffId) end function XRestaurant:SetAreaBuffId(areaType, buffId) local map = self._AreaTypeBuff map[areaType] = buffId self:SetProperty("_AreaTypeBuff", map) end function XRestaurant:CheckAreaBuffUnlock(areaType) local minLevel = XRestaurantConfigs.GetAreaBuffUnlockMinLevel(areaType) return self._Level >= minLevel end --endregion------------------getter and setter finish------------------ --region ------------------private start------------------- ---@private function XRestaurant:_InitStaffList() local characters = XRestaurantConfigs.GetCharacters() local staffMap = {} for id, _ in pairs(characters or {}) do ---@type XRestaurantStaff local staff = XRestaurantStaff.New(id) staff:UpdateInfo(XRestaurantConfigs.IsFreeCharacter(id), 1) staffMap[id] = staff end self:SetProperty("_StaffMap", staffMap) end function XRestaurant:_InitProductList() local ingredients = XRestaurantConfigs.GetIngredients() local ingredientMap = {} for id, _ in pairs(ingredients or {}) do local ingredient = XIngredient.New(id) ingredientMap[id] = ingredient end local foods = XRestaurantConfigs.GetFoods() local foodMap = {} for id, _ in pairs(foods or {}) do local food = XFood.New(id) foodMap[id] = food end self:SetProperty("_IngredientMap", ingredientMap) self:SetProperty("_FoodMap", foodMap) end function XRestaurant:_InitWorkBench() local level = self._Level local ingredientCount = XRestaurantConfigs.GetIngredientCounterNum(level) local foodCount = XRestaurantConfigs.GetFoodCounterNum(level) local saleCount = XRestaurantConfigs.GetSaleCounterNum(level) local initBench = function(count, class, list) for i = 1, count do local bench = list[i] or class.New(i) list[i] = bench end end initBench(ingredientCount, XIngredientWorkBench, self._IngredientWorkBenches) initBench(foodCount, XCookingWorkBench, self._CookingWorkBenches) initBench(saleCount, XSalesWorkBench, self._SalesWorkBenches) ---@type table self._AreaMap2Benches = { [XRestaurantConfigs.AreaType.IngredientArea] = self._IngredientWorkBenches, [XRestaurantConfigs.AreaType.FoodArea] = self._CookingWorkBenches, [XRestaurantConfigs.AreaType.SaleArea] = self._SalesWorkBenches, } end --- 材料生产速度 ---@param productId number 材料Id ---@param timeUnit number 单位时间 ---@return number -------------------------- function XRestaurant:_GetIngredientProduceTotalSpeed(productId, timeUnit) local speed = 0 --生产无需原材料 for _, bench in pairs(self._IngredientWorkBenches) do --空闲状态 if bench:IsFree() then goto continue end --未生产目标物品 if bench:GetProperty("_ProductId") ~= productId then goto continue end speed = speed + bench:GetProductiveness(timeUnit) ::continue:: end return speed end --- 材料消耗速度 ---@param productId number 材料Id ---@param timeUnit number 单位时间 ---@return number -------------------------- function XRestaurant:_GetIngredientConsumeTotalSpeed(productId, timeUnit) local speed = 0 for _, bench in pairs(self._CookingWorkBenches) do --空闲状态 if bench:IsFree() then goto continue end speed = speed + bench:GetConsumption(productId, timeUnit) ::continue:: end return speed end --- 食物生产速度 ---@param productId number 材料Id ---@param timeUnit number 单位时间 ---@return number -------------------------- function XRestaurant:_GetFoodProduceTotalSpeed(productId, timeUnit) local speed = 0 for _, bench in pairs(self._CookingWorkBenches) do --空闲状态 if bench:IsFree() then goto continue end --未生产目标物品 if bench:GetProperty("_ProductId") ~= productId then goto continue end speed = speed + bench:GetProductiveness(timeUnit) ::continue:: end return speed end function XRestaurant:_GetFoodConsumeTotalSpeed(productId, timeUnit) local speed = 0 for _, bench in pairs(self._SalesWorkBenches) do --空闲状态 if bench:IsFree() then goto continue end speed = speed + bench:GetConsumption(productId, timeUnit) ::continue:: end return speed end function XRestaurant:_GetSaleProduceTotalSpeed(productId, timeUnit) return 0 end function XRestaurant:_GetSaleConsumeTotalSpeed(productId, timeUnit) return self:_GetFoodConsumeTotalSpeed(productId, timeUnit) end --endregion------------------private finish------------------ --region ------------------simulation start------------------- function XRestaurant:StartSimulation() if not SimulationTimer then LastSimulationTime = XTime.GetServerNowTimestamp() SimulationTimer = XScheduleManager.ScheduleForever(function() self:Simulation() end, XScheduleManager.SECOND, SimulationDelay) end end function XRestaurant:StopSimulation() if SimulationTimer then XScheduleManager.UnSchedule(SimulationTimer) SimulationTimer = nil end end function XRestaurant:Simulation() --每秒执行一次 local now = XTime.GetServerNowTimestamp() local second = now - LastSimulationTime local room = XDataCenter.RestaurantManager.GetRoom() if room then room:Simulation(now) end local sort = self:SortSimulationWorkBench(self._IngredientWorkBenches, XRestaurantConfigs.AreaType.IngredientArea) for _, ingredient in pairs(sort) do ingredient:Simulation(second) end sort = self:SortSimulationWorkBench(self._CookingWorkBenches, XRestaurantConfigs.AreaType.FoodArea) for _, food in pairs(sort) do food:Simulation(second) end sort = self:SortSimulationWorkBench(self._SalesWorkBenches, XRestaurantConfigs.AreaType.SaleArea) for _, sale in pairs(sort) do sale:Simulation(second) end --避免长时间待着场景内,内存炸了 if CS.XLuaEngine.Env.Memroy - self._EnterRoomMemory > LuaMemoryLimit then LuaGC() self:UpdateLuaMemory() end LastSimulationTime = now end ---@param benchList XRestaurantWorkBench[] function XRestaurant:SortSimulationWorkBench(benchList, areaType) if XTool.IsTableEmpty(benchList) then return {} end if not self:CheckNewSort(areaType) then return benchList end local tmpList = {} for _, bench in pairs(benchList) do if bench:IsRunning() then table.insert(tmpList, bench) end end table.sort(tmpList, function(a, b) local runningA = a:IsRunning() local runningB = b:IsRunning() if runningA ~= runningB then return runningA end local priorityA = a:GetWorkPriority() local priorityB = b:GetWorkPriority() if priorityA ~= priorityB then return priorityA < priorityB end local updateTimeA = a:GetProperty("_UpdateTime") local updateTimeB = b:GetProperty("_UpdateTime") if updateTimeA ~= updateTimeB then return updateTimeA < updateTimeB end return a:GetProperty("_Id") < b:GetProperty("_Id") end) return tmpList end --- 检查当前趋于工作台是否需要重新排序 ---@param areaType number 区域类型 ---@return boolean -------------------------- function XRestaurant:CheckNewSort(areaType) local value = self._AreaSortMark[areaType] return not value end --- 标记当前区域需要排序 ---@param areaType number 区域类型 ---@return void -------------------------- function XRestaurant:MarkNewSort(areaType) self._AreaSortMark[areaType] = true end --endregion------------------Simulation finish------------------ function XRestaurant:NotifyLevelConditionEventChange() self:SetProperty("_EventLevelConditionChange", self._EventLevelConditionChange + 1) end function XRestaurant:NotifyBuffRedPointChange() self:SetProperty("_BuffRedPointMarkCount", self._BuffRedPointMarkCount + 1) end function XRestaurant:NotifyMenuRedPointChange() self:SetProperty("_MenuRedPointMarkCount", self._MenuRedPointMarkCount + 1) end function XRestaurant:OnActivityEnd() for key, value in pairs(default) do self[key] = value end end return XRestaurant