diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 670de340..9526a0c5 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -1,4 +1,24 @@ --------------------------------------------------------------------------------------------------- +Version: 1.3.0 +Date: 2023-10-10 + Features: + - Added improved combinator display sprites (further improvements coming) - contributed by jagoly + - The manager gui now displays control signals - contributed by Shadowvoices + - The manager gui now excludes requests that do not exceed the request threshold - contributed by Shadowvoices + Bugfixes: + - Fixed a crash when clicking on a combinator when the GUI is open - contributed by PeteyPii + - Fixed a crash when setting a combinator to depot mode without a network - contributed by download13 and TheXIFC + - Stations with provider item thresholds can no longer generate empty train orders - contributed by svr8450 + - Added missing loader entity type to the automatic allow-list - contributed by gillett-hernandez + - Fixed a case where combinator changes not being applied for depots and refuelers - contributed by jagoly + - Fixed provide/request orders for the same item getting generated simultaneously - contributed by jagoly + - Fixed a crash when opening the manager when adding cybersyn to an existing save - contributed by Mjonir + - Fixed a crash when enabling the manager on an existing save - contributed by freyacodes + Translation: + - Swedish language added - contributed by Sharparam + - Chinese language update - contributed by luaotix + - Russian language update - contributed by Eldrinn-Elantey +--------------------------------------------------------------------------------------------------- Version: 1.2.16 Date: 2023-5-14 Bugfixes: diff --git a/cybersyn/graphics/combinator/cybernetic-displays.png b/cybersyn/graphics/combinator/cybernetic-displays.png index 7d5d36a0..97547c2c 100644 Binary files a/cybersyn/graphics/combinator/cybernetic-displays.png and b/cybersyn/graphics/combinator/cybernetic-displays.png differ diff --git a/cybersyn/graphics/combinator/hr-cybernetic-displays.png b/cybersyn/graphics/combinator/hr-cybernetic-displays.png index 280cc00e..17749ec3 100644 Binary files a/cybersyn/graphics/combinator/hr-cybernetic-displays.png and b/cybersyn/graphics/combinator/hr-cybernetic-displays.png differ diff --git a/cybersyn/info.json b/cybersyn/info.json index 739a874d..4af65bd0 100644 --- a/cybersyn/info.json +++ b/cybersyn/info.json @@ -1,6 +1,6 @@ { "name": "cybersyn", - "version": "1.2.16", + "version": "1.3.0", "title": "Project Cybersyn", "author": "Mami", "factorio_version": "1.1", diff --git a/cybersyn/locale/ru/manager.cfg b/cybersyn/locale/ru/manager.cfg index 1b735427..95b5f560 100644 --- a/cybersyn/locale/ru/manager.cfg +++ b/cybersyn/locale/ru/manager.cfg @@ -21,7 +21,7 @@ no-alerts=[img=warning-white] Тревог нет no-stations=[img=warning-white] Станций нет ;not-available=Not available no-trains=[img=warning-white] Поездов нет -open-station-gui=Открыть интерфейс станции\n[font=default-semibold][color=128,206,240]Shift:[/color][/font] Открыть станцию на карте\n[font=default-semibold][color=128,206,240]Control:[/color][/font] Открыть интерфейс кибернетического комбинатора станции\n[font=default-semibold][color=128,206,240]Alt:[/color][/font] Открыть интерфейс кибернетического комбинатора контроля станции +open-station-gui=Открыть интерфейс станции\n[font=default-semibold][color=128,206,240]Shift:[/color][/font] Открыть станцию на карте\n[font=default-semibold][color=128,206,240]Control:[/color][/font] Открыть интерфейс кибернетического комбинатора станции\n[font=default-semibold][color=128,206,240]Alt:[/color][/font] Открыть интерфейс кибернетического комбинатора управления станции open-train-gui=Открыть интерфейс поезда provided=Снабжение ;provided-requested-description=Green = provided\nRed = requested diff --git a/cybersyn/locale/sv-SE/base.cfg b/cybersyn/locale/sv-SE/base.cfg new file mode 100644 index 00000000..1849c1a5 --- /dev/null +++ b/cybersyn/locale/sv-SE/base.cfg @@ -0,0 +1,103 @@ +[mod-description] +cybersyn=Använder cybernetiska kombinatorer för att skapa funktionsfyllda tågnätverk för logistik. Du kan koordinera de ekonomiska in- och utflödena för hela din megabas med bara den här modden. + +[mod-setting-name] +cybersyn-enable-planner=Aktivera centralplanering +cybersyn-ticks-per-second=Centralplaneringsuppdateringar per sekund +cybersyn-update-rate=Centralplaneringuppdateringsfrekvens +cybersyn-request-threshold=Standardbeställningströskel +cybersyn-priority=Standardprioritet +cybersyn-locked-slots=Standardvärde för låsta platser per lastvagn +cybersyn-network-flag=Standardnätverksmask +cybersyn-fuel-threshold=Bränsletröskel +cybersyn-depot-bypass-enabled=Hoppa över depåer +cybersyn-warmup-time=Stationsuppvärmningstid (sek) +cybersyn-stuck-train-time=Timeout för tåg som fastnat (sek) +cybersyn-allow-cargo-in-depot=Tillåt last i depåer +cybersyn-invert-sign=Invertera kombinatorers utsignaler (förlegad) +cybersyn-manager-enabled=Aktivera Cybersyn-GUI:t +cybersyn-manager-update-rate=Uppdateringsfrekvens för hanteraren +cybersyn-manager-result-limit=Max antal entiteter som visas på GUI-sidor. + +[mod-setting-description] +cybersyn-enable-planner=Aktivera eller avaktivera centralplaneringsalgoritmen. När den är avstängd kommer inga nya tåg att skickas iväg. +cybersyn-ticks-per-second=Antal gånger per sekund som centralplaneraren ska uppdatera nätverksstatusen och planera leveranser. Värdet rundas upp till en divisor 60. Om satt till 0 stoppas alla avsändningar. +cybersyn-update-rate=Antal stationer per tick som uppdateras eller får leveranser planerade åt gången. Större nummer låter centralplaneraren hålla sig uppdaterade gentemot nätverkets status, men kräver mer prestanda. +cybersyn-request-threshold=Standardvärde för förfrågningströskeln när en specifik tröskelsignal inte ges till en station. När en station tar emot en negativ lastsignal som är större än förfrågningströskeln, förutsatt att det finns en annan station med en positiv signal som är större än tröskeln, planeras en leverans av lasten mellan de två stationerna. +cybersyn-priority=Standardvärde för prioritet när en prioritetssignal inte ges till en station, depå, eller bränslestation. Stationer med högre prioritet tar emot leveranser innan stationer med lägre prioritet. +cybersyn-locked-slots=Standardvärde för antal låsta platser per lastvagn när en signal för "låsta platser per lastvagn" inte ges till stationen. När en leverantörsstation har ett värde X för "låsta platser per lastvagn", leder det till att tåg som utför leveranser från den stationen får sin order justerad så att varje lastvagn har åtminstone X platser som lämnas tomma. Detta är nödvändigt för att möjliggöra leverantörsstationer som kan leverera fler än en typ av last. +cybersyn-network-flag=Standardvärde för nätverksmasken (en samling subnätverk) en station konfigureras med om ingen signal för nätverksmask ges till den. Heltalet tolkas bitvis för 32 möjliga subnätverk att välja mellan. +cybersyn-fuel-threshold=Andelen av ett tågs bränsleinnehåll som måste vara fylld för att tåget ska hoppa över bränslestationer. När värdet är 1 kommer tåg alltid att besöka en bränslestation efter varje utförd leverans. +cybersyn-depot-bypass-enabled=Med den här inställningen aktiverad kan tåg, efter att de slutfört sin leverans och eventuell påfyllning av bränsle, få en ny order från nätverket utan att först återvända till sin depå. +cybersyn-warmup-time=Antal sekunder som en Cybernetisk kombinator väntar innan den ansluter till Cybersyn-nätverket. Det här tillåter tid för ändringar eller korrigeringar till kretsnätverket innan tåg börjar skickas till en nyligen byggd station. +cybersyn-stuck-train-time=Antal sekunder räknat från ett tågs avgångstid som en varning skickas för att meddela att ett tåg antagligen fastnat och inte har slutfört sin leverans. Spelaren kommer antagligen behöva felsöka sitt nätverk för att få loss tåget. +cybersyn-allow-cargo-in-depot=Tillåter att tåg anländer till en depå med last kvar i sina vagnar. Inga varningar kommer skapas och tåget hålls inte kvar i depån. Dessutom, för tåg med en order att besöka en beställarstation som har "Inaktivetetsvillkor" ikryssat, kommer de att vänta på inaktivetet istället för tom last. Användbart för att skapa tågsystem där depåer hanterar överflödig last. Endast för avancerade användare. +cybersyn-invert-sign=Invertera (ändra positivt till negativt och vice versa) utsignalen från Cybernetiska kombinatorer till att vara som de är i LTN eller tidigare versioner av Projekt Cybersyn. +cybersyn-manager-enabled=Ger en översikt över alla tåg och stationer som är anslutna till Cybersyn-nätverket. Gränssnittet är under utveckling och kan leda till många krascher. +cybersyn-manager-updates-per-second=Ställer in hur ofta gränssnittet för Cybersyn-hanteraren uppdateras. Cybersyn-hanteraren måste vara aktiverad för att den här inställningen ska ha någon effekt. +cybersyn-manager-result-limit=Sätter en gräns på antalet matchande entiteter (t.ex. stationer, tåg) för att begränsa tiden det tar att uppdatera när listan uppdateras.\nSätt till -1 för att visa allt. + +[item-name] +cybersyn-combinator=__ENTITY__cybersyn-combinator__ + +[item-description] +cybersyn-combinator=Placera vid en tågstation för att lägga till den till Cybersyn-tågnätverket. Stationen kan nu beställa eller leverera last som skickas in till kombinatorn via signaler i kretsnätverket. + +[entity-name] +cybersyn-combinator=Cybernetisk kombinator +cybersyn-combinator-output=Cybernetisk kombinator-utsignaler + +[entity-description] +cybersyn-combinator=Har 5 olika lägen. Det behövs bara stationsläge och depåläge för att komma igång. + +[technology-name] +cybersyn-train-network=Cybersyn tågnätverk + +[technology-description] +cybersyn-train-network=Tågstationsenheter som kan koordinera in- och utflöden för en hel ekonomi. + +[virtual-signal-name] +cybersyn-priority=Stationsprioritet +cybersyn-request-threshold=Beställningströskel +cybersyn-locked-slots=Låsta platser per lastvagn + +[cybersyn-messages] +nonempty-train=Ett tåg hålls kvar i depån eftersom det fortfarande innehåller last +unexpected-train=Ett tåg har oväntat återvänt till depån utan att slutföra sin leverans +stuck-train=Ett tåg har fastnat +cannot-path-between-surfaces=Ett tåg försöker leverera mellan två olika ytor som inte är sammankopplade. Testa att använda separata nätverk för ytorna. +depot-broken=Ett tåg är vilse för att dess depå försvann +refueler-broken=Ett tåg är vilse för att dess bränslestation försvann +station-broken=Ett tåg är vilse för att en av dess leveransstationer försvann +train-at-incorrect=Ett tåg är parkerat vid en station den inte var planerad att leverera till +missing-train=Kunde inte hitta något tåg på rätt nätverk för att utföra leverans från __2__ till __1__ +no-train-has-capacity=Kunde inte hitta något tåg med tillräcklig kapacitet för att utföra leverans från __2__ till __1__ +no-train-matches-r-layout=Kunde inte hitta något tåg på listan av tillåtna tåg för __1__ för att utföra en leverans +no-train-matches-p-layout=Kunde inte hitta något tåg på listan av tillåtna tåg för __2__ för att leverera till __1__ + +[cybersyn-gui] +combinator-title=__ENTITY__cybersyn-combinator__ +operation=Läge +comb1=Station +depot=Depå +refueler=Bränslestation +comb2=Stationskontroll +wagon-manifest=Vagnkontroll +switch-provide=Leverantör +switch-request=Beställare +switch-provide-tooltip=Lås den här stationen till att endast leverera föremål till nätverket. I ospecificerat läge kan den både leverera och beställa. +switch-request-tooltip=Lås den här stationen till att endast beställa föremål från nätverket. I ospecificerat läge kan den både beställa och leverera. +network=Nätverk +network-tooltip=En signal som används för att identifiera vilket nätverk den här kombinatorn tillhör. Tåg skickas endast endast från depåer till leverantörer och beställare om de alla delar samma signal. +allow-list-description=Automatiskt tillåtna tåg +allow-list-tooltip=Om aktiverad kommer den här stationen automatiskt tillåta tåg att använda den om alla vagnar på tåget kan lastas på eller av vid den. Annars används ingen automatisk logik och alla tåg kan använda staionen oavsett. +is-stack-description=Stapeltrösklar +is-stack-tooltip=Alla beställningströsklar för den här stationen tolkas som ett antal staplar istället för styckantal. Trösklar för vätskor påverkas inte. +enable-inactive-description=Inaktivitetsvillkor +enable-inactive-tooltip=Om aktiverad krävs det att tåg vid en leverantör väntar på inaktivitet innan det lämnar, även om ordern redan har fyllts. Detta är främst användbart för att förhindra att lastkranar fastnar med saker i sina händer. +use-same-depot-description=Använd samma depå +use-same-depot-tooltip=Om aktiverad kommer tåg som lämnar från den här depån alltid att återvända till samma station. Annars är tåget tillåtet att återvända till en annan depåstation med samma namn som den här. +depot-bypass-description=Hoppa över depå +depot-bypass-tooltip=Tåg från den här depån kan få nya ordrar utan att först parkera vid depån, om de inte har en pågående order. De kommer fortfarande att återvända till depån om de har låg bränslenivå och det inte finns några bränslestationer tillgängliga på nätverket. +enable-slot-barring-description=Blockera ofiltrerade platser +enable-slot-barring-tooltip=Platser i intilliggande vagn som inte har filter blockeras istället så att föremål inte kan lastas i dem. diff --git a/cybersyn/locale/sv-SE/manager.cfg b/cybersyn/locale/sv-SE/manager.cfg new file mode 100644 index 00000000..1613787e --- /dev/null +++ b/cybersyn/locale/sv-SE/manager.cfg @@ -0,0 +1,57 @@ +[mod-name] +cybersyn=Projekt Cybersyn + +[controls] +cybersyn-toggle-gui=Visa/dölj Cybersyn-hanteraren + +[cybersyn-gui] +alerts=Larm +all-paren=(Alla) +control-signals=Styrsignaler +;history=Historik +in-transit=Transporterar +inventory=Innehåll +layout=Tåglayout +name=Namn +network-name-label=Nätverksfilter: +network-id-label=Nätverks-ID: +network-id=Nätverks-ID +no-alerts=[img=warning-white] Inga larm +;no-history=[img=warning-white] Ingen historik +no-stations=[img=warning-white] Inga stationer +;not-available=Ej tillgänglig +no-trains=[img=warning-white] Inga tåg +open-station-gui=Öppna stations-GUI\n[font=default-semibold][color=128,206,240]Skift:[/color][/font] Öppna station på kartan\n[font=default-semibold][color=128,206,240]Kontroll:[/color][/font] Öppna stationens Cybernetiska kombinator\n[font=default-semibold][color=128,206.240]Alt:[/color][/font] Öppna stationens Cybernetiska stationskontrollkombinator +open-train-gui=Öppna tåg-GUI +provided=Levererat +;provided-requested-description=Grönt = levererat\nRött = beställt +provided-requested=Levererat / beställt +;refresh-tooltip=Uppdatera\n[font=default-semibold][color=128,206,240]Skift:[/color][/font] Slå på/av autouppdatering +requested=Beställt +search-label=Stationsnamn: +search-item-label=Lastfilter: +shipment=Leverans +shipments=Leveranser +stations=Stationer +status=Nätverkssignal +surface-label=Yta: +time=Tid +train-id=Tåg-ID +trains=Tåg + +[cybersyn-message] +error-cybernetic-combinator-not-found=Kunde inte hitta en Cybernetisk kombinator för stationen. +error-station-control-combinator-not-found=Kunde inte hitta en Cybernetisk stationskontrollkombinator för stationen. +error-station-is-invalid=Stationen är felaktig, var god uppdatera GUI:t. +error-train-is-invalid=Tåget är felaktigt, var god uppdatera GUI:t. +error-cross-surface-camera-invalid=Kan inte flytta kameran till en entitet på en annan yta! + +[cybersyn-mod-setting-description] +iterations-per-tick=Minska numret om du har prestandaproblem. + +[cybersyn-mod-setting-name] +history-length=Historiklängd +iterations-per-tick=Iterationer per tick [img=info] + +[shortcut-name] +cybersyn-toggle-gui=Visa/dölj Cybersyn-hanteraren diff --git a/cybersyn/locale/zh-CN/base.cfg b/cybersyn/locale/zh-CN/base.cfg index c64ecc7e..9d4a533f 100644 --- a/cybersyn/locale/zh-CN/base.cfg +++ b/cybersyn/locale/zh-CN/base.cfg @@ -14,7 +14,7 @@ cybersyn-locked-slots=默认每车厢锁定格数 cybersyn-network-flag=默认网络掩码 cybersyn-fuel-threshold=燃料阈值 cybersyn-depot-bypass-enabled=启用车库绕行 -cybersyn-warmup-time=车站预热时间(秒) +cybersyn-warmup-time=车站预备时间(秒) cybersyn-stuck-train-time=列车卡住超时(秒) cybersyn-allow-cargo-in-depot=允许车库中存放货物 cybersyn-invert-sign=反转运算器输出(已弃用) @@ -34,7 +34,7 @@ cybersyn-fuel-threshold=列车的燃料库存必须达到多少百分比才能 cybersyn-depot-bypass-enabled=若选中,则当列车完成交付和加油后,可以在返回其车库之前从网络中接受新订单。 cybersyn-warmup-time=协同控制运算器在连接到Cybersyn网络之前要等待多少秒。这是一个宽限期,便于在列车开始调度到一个新站台前,修改或纠正信号网络。 cybersyn-stuck-train-time=在列车派遣后的这么多秒后,将发送警报,以让您知道列车可能卡住了,并且无完成交付。玩家可能需要调试其网络以使列车脱困。 -cybersyn-allow-cargo-in-depot=若选中,则允许列车在车库中装载货物。不会生成任何警报,列车也不会被拦住。此外,具有访问请求站点并勾选了“非活动状态”的订单的列车将等待非活动状态,而不是等待空货物。对于创建由车库处理多余货物的列车系统非常有用。仅适用于高水准玩家。 +cybersyn-allow-cargo-in-depot=若选中,则允许列车在车库中装载货物。不会生成任何警报,列车也不会被拦住。此外,具有访问请求站点并勾选了“静止状态”的订单的列车将等待静止状态,而非等待清空货物。这对于创建由车库处理多余货物的列车系统非常有用。仅适用于高水准玩家。 cybersyn-invert-sign=翻转协同控制运算器输出的信号,使其与LTN或Project Cybersyn早期版本中的信号相同。 cybersyn-manager-enabled=允许查看连接到Cybersyn的所有列车和车站。此管理器界面目前正处于开发中,可能会导致多次崩溃。 cybersyn-manager-updates-per-second=控制Cybersyn管理器界面刷新的频率。必须将Cybersyn管理器设置为启用才能生效。 @@ -57,7 +57,7 @@ cybersyn-combinator=有5种不同的模式。但您仅需站台和车库模式 cybersyn-train-network=Cybersyn 列车协同控制网络 [technology-description] -cybersyn-train-network=站台控制器能够协调整体的输入和输出。 +cybersyn-train-network=一款列车站台控制器,能够统筹全局运输的物流调度。 [virtual-signal-name] cybersyn-priority=站台优先级 @@ -148,9 +148,9 @@ cybersyn-toggle-gui=切换Cybersyn管理器 [cybersyn-message] error-cybernetic-combinator-not-found=找不到该车站的协同控制运算器。 error-station-control-combinator-not-found=找不到该车站的协同控制运算器。 -error-station-is-invalid=车站无效,请刷新管理器界面。 -error-train-is-invalid=列车无效,请刷新管理器界面。 -error-cross-surface-camera-invalid=无法将相机移动到不同表面上的实体上! +error-station-is-invalid=车站无效,请刷新管理器。 +error-train-is-invalid=列车无效,请刷新管理器。 +error-cross-surface-camera-invalid=无法将视角移动至不同表面上的实体上! [cybersyn-mod-setting-description] iterations-per-tick=若您遇到性能问题,降低本数值。 @@ -160,4 +160,4 @@ history-length=历史记录长度 iterations-per-tick=每tick的迭代次数[img=info] [shortcut-name] -cybersyn-toggle-gui=切换Cybersyn管理器 +cybersyn-toggle-gui=Cybersyn管理器 diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 9428d4d3..37d66172 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -157,11 +157,17 @@ function create_manifest(map_data, r_station_id, p_station_id, train_id, primary end local p_effective_item_count = p_station.item_p_counts[item_name] --could be an item that is not present at the station + local effective_threshold local override_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] if override_threshold and p_station.is_stack and item_type == "item" then override_threshold = override_threshold*get_stack_size(map_data, item_name) end - if p_effective_item_count and p_effective_item_count >= (override_threshold or r_threshold) then + if override_threshold and override_threshold <= r_threshold then + effective_threshold = override_threshold + else + effective_threshold = r_threshold + end + if p_effective_item_count and p_effective_item_count >= effective_threshold then local item = {name = item_name, type = item_type, count = min(-r_effective_item_count, p_effective_item_count)} if item_name == primary_item_name then manifest[#manifest + 1] = manifest[1] @@ -281,6 +287,12 @@ local function tick_dispatch(map_data, mod_settings) goto continue end + --don't request when already providing + local item_deliveries = station.deliveries[item_name] + if item_deliveries and item_deliveries < 0 then + goto continue + end + local threshold = station.r_threshold local prior = station.priority local item_threshold = station.item_thresholds and station.item_thresholds[item_name] or nil @@ -294,6 +306,7 @@ local function tick_dispatch(map_data, mod_settings) goto continue end + --prioritize by last delivery time if priorities are equal if prior == best_r_prior and station.last_delivery_tick > best_timestamp then goto continue end @@ -342,7 +355,7 @@ local function tick_dispatch(map_data, mod_settings) ---@type uint local j = 1 while j <= #p_stations do - local p_flag, r_flag, netand, best_p_train_id, best_t_prior, best_capacity, best_t_to_p_dist, effective_count, override_threshold, p_prior, best_p_to_r_dist, effective_threshold, slot_threshold + local p_flag, r_flag, netand, best_p_train_id, best_t_prior, best_capacity, best_t_to_p_dist, effective_count, override_threshold, p_prior, best_p_to_r_dist, effective_threshold, slot_threshold, item_deliveries local p_station_id = p_stations[j] local p_station = stations[p_station_id] @@ -350,6 +363,12 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue end + --don't provide when already requesting + item_deliveries = p_station.deliveries[item_name] + if item_deliveries and item_deliveries > 0 then + goto p_continue + end + p_flag = get_network_mask(p_station, network_name) r_flag = get_network_mask(r_station, network_name) netand = band(p_flag, r_flag) @@ -492,14 +511,16 @@ local function tick_dispatch(map_data, mod_settings) create_delivery(map_data, r_station_id, p_station_id, best_train_id, manifest) return false else - if correctness == 1 then - send_alert_missing_train(r_station.entity_stop, closest_to_correct_p_station.entity_stop) - elseif correctness == 2 then - send_alert_no_train_has_capacity(r_station.entity_stop, closest_to_correct_p_station.entity_stop) - elseif correctness == 3 then - send_alert_no_train_matches_r_layout(r_station.entity_stop, closest_to_correct_p_station.entity_stop) - elseif correctness == 4 then - send_alert_no_train_matches_p_layout(r_station.entity_stop, closest_to_correct_p_station.entity_stop) + if closest_to_correct_p_station then + if correctness == 1 then + send_alert_missing_train(r_station.entity_stop, closest_to_correct_p_station.entity_stop) + elseif correctness == 2 then + send_alert_no_train_has_capacity(r_station.entity_stop, closest_to_correct_p_station.entity_stop) + elseif correctness == 3 then + send_alert_no_train_matches_r_layout(r_station.entity_stop, closest_to_correct_p_station.entity_stop) + elseif correctness == 4 then + send_alert_no_train_matches_p_layout(r_station.entity_stop, closest_to_correct_p_station.entity_stop) + end end if band(r_station.display_state, 2) == 0 then r_station.display_state = r_station.display_state + 2 diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index e50d3c98..69da8331 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -131,6 +131,7 @@ ---@field public react_to_train_early_to_depot boolean --interface setting ---@field public enable_manager boolean ---@field public manager_ups double +---@field public manager_enabled boolean --if this is uncommented it means there are migrations to write diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 6265a076..263aa44e 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -89,13 +89,6 @@ local function handle_drop_down(e) set_comb_operation(comb, MODE_PRIMARY_IO) elseif element.selected_index == 2 then set_comb_operation(comb, MODE_DEPOT) - --prevent the use of the each signal with depots - local network = element.parent.parent.bottom.network--[[@as LuaGuiElement]] - local signal = network.elem_value--[[@as SignalID]] - if signal.name == NETWORK_EACH then - network.elem_value = nil - set_comb_network_name(comb, nil) - end elseif element.selected_index == 3 then set_comb_operation(comb, MODE_REFUELER) elseif element.selected_index == 4 then diff --git a/cybersyn/scripts/gui/inventory.lua b/cybersyn/scripts/gui/inventory.lua index 20405d99..7034d27f 100644 --- a/cybersyn/scripts/gui/inventory.lua +++ b/cybersyn/scripts/gui/inventory.lua @@ -132,10 +132,17 @@ function inventory_tab.build(map_data, player_data) inventory_provided[item.name] = inventory_provided[item.name] + count end else - if inventory_requested[item.name] == nil then - inventory_requested[item.name] = count - else - inventory_requested[item.name] = inventory_requested[item.name] + count + local r_threshold = station.item_thresholds and station.item_thresholds[item.name] or station.r_threshold + if station.is_stack and item_type == "item" then + r_threshold = r_threshold*get_stack_size(map_data, item.name) + end + + if -count >= r_threshold then + if inventory_requested[item.name] == nil then + inventory_requested[item.name] = count + else + inventory_requested[item.name] = inventory_requested[item.name] + count + end end end end diff --git a/cybersyn/scripts/gui/main.lua b/cybersyn/scripts/gui/main.lua index 7628c426..52bd545a 100644 --- a/cybersyn/scripts/gui/main.lua +++ b/cybersyn/scripts/gui/main.lua @@ -51,6 +51,15 @@ function manager_gui.on_lua_shortcut(e) if e.element then if e.element.name == "manager_window" then manager.wrapper(e, manager.handle.manager_toggle) + elseif e.element.name == COMBINATOR_NAME and e.name == defines.events.on_gui_closed then + -- With the manager enabled, this handler overwrites the combinator's + -- on_gui_close handler. Copy the logic to close the combinator's GUI here + -- as well. + local player = game.get_player(e.player_index) + if not player then return end + if player.gui.screen[COMBINATOR_NAME] then + player.gui.screen[COMBINATOR_NAME].destroy() + end end else manager.wrapper(e, manager.handle.manager_toggle) @@ -60,9 +69,10 @@ end -function manager_gui.on_player_created(e) - local player = game.get_player(e.player_index) +local function create_player(player_index) + local player = game.get_player(player_index) if not player then return end + local player_data = { search_network_mask = -1, trains_orderings = {}, @@ -71,12 +81,16 @@ function manager_gui.on_player_created(e) refs = manager.create(player), selected_tab = "stations_tab", } - global.manager.players[e.player_index] = player_data + global.manager.players[player_index] = player_data --manager.update(global, player, player_data) --top_left_button_update(player, player_data) end +function manager_gui.on_player_created(e) + create_player(e.player_index) +end + function manager_gui.on_player_removed(e) global.manager.players[e.player_index] = nil end @@ -147,9 +161,20 @@ end function manager_gui.on_migration() + if not global.manager then + manager_gui.on_init() + end + + for i, p in pairs(game.players) do + if global.manager.players[i] == nil then + create_player(i) + end + end + for i, v in pairs(global.manager.players) do manager_gui.reset_player(i, v) end + init_items(global.manager) end diff --git a/cybersyn/scripts/gui/stations.lua b/cybersyn/scripts/gui/stations.lua index 6f1b4c19..4948a55d 100644 --- a/cybersyn/scripts/gui/stations.lua +++ b/cybersyn/scripts/gui/stations.lua @@ -250,7 +250,7 @@ function stations_tab.build(map_data, player_data, query_limit) gui.add(refs.provided_requested_table, util.slot_table_build_from_station(station)) gui.add(refs.shipments_table, util.slot_table_build_from_deliveries(station)) - gui.add(refs.control_signals_table, util.slot_table_build_from_control_signals(station)) + gui.add(refs.control_signals_table, util.slot_table_build_from_control_signals(station, map_data)) end diff --git a/cybersyn/scripts/gui/util.lua b/cybersyn/scripts/gui/util.lua index dd7c7f68..e06debe0 100644 --- a/cybersyn/scripts/gui/util.lua +++ b/cybersyn/scripts/gui/util.lua @@ -171,10 +171,11 @@ end --- @param station Station --- @return GuiElemDef[] -function util.slot_table_build_from_control_signals(station) +function util.slot_table_build_from_control_signals(station, map_data) ---@type GuiElemDef[] local children = {} local comb1_signals, comb2_signals = get_signals(station) + if comb1_signals then for _, v in pairs(comb1_signals) do local item = v.signal @@ -205,6 +206,68 @@ function util.slot_table_build_from_control_signals(station) ::continue:: end end + + if comb2_signals then + for _, v in pairs(comb2_signals) do + local item = v.signal + local count = v.count + local name = item.name + local sprite = "" + local color = "default" + + if item.type == "item" or item.type == "fluid" then + local sprite, img_path, item_string = util.generate_item_references(name) + if sprite ~= nil then + local color + if count > 0 then + color = "green" + else + color = "blue" + end + end + + if station.is_stack and item.type == "item" then + count = count * get_stack_size(map_data, name) + end + + if game.is_valid_sprite_path(sprite) then + children[#children + 1] = { + type = "sprite-button", + enabled = false, + style = "ltnm_small_slot_button_" .. color, + sprite = sprite, + tooltip = { + "", + img_path, + item_string, + "\n"..format.number(count), + }, + number = count + } + end + + elseif item.type == "virtual" then + sprite = "virtual-signal" .. "/" .. name + if game.is_valid_sprite_path(sprite) then + children[#children + 1] = { + type = "sprite-button", + enabled = false, + style = "ltnm_small_slot_button_" .. color, + sprite = sprite, + tooltip = { + "", + "[img=virtual-signal." .. name .. "]", + { "virtual-signal-name." .. name }, + "\n"..format.number(count), + }, + number = count + } + end + end + ::continue:: + end + end + return children end diff --git a/cybersyn/scripts/layout.lua b/cybersyn/scripts/layout.lua index 46b82b19..730fec72 100644 --- a/cybersyn/scripts/layout.lua +++ b/cybersyn/scripts/layout.lua @@ -215,7 +215,7 @@ function set_p_wagon_combs(map_data, station, train) if carriage.type == "cargo-wagon" then local inv = carriage.get_inventory(defines.inventory.cargo_wagon) if inv then - ---@type ConstantCombinatorParameters + ---@type ConstantCombinatorParameters[] local signals = {} local inv_filter_i = 1 @@ -421,7 +421,7 @@ function unset_wagon_combs(map_data, stop) end end -local type_filter = {"inserter", "pump", "arithmetic-combinator", "loader-1x1"} +local type_filter = {"inserter", "pump", "arithmetic-combinator", "loader-1x1", "loader"} ---@param map_data MapData ---@param stop Station|Refueler ---@param is_station_or_refueler boolean @@ -543,7 +543,7 @@ function reset_stop_layout(map_data, stop, is_station_or_refueler, forbidden_ent end end end - elseif entity.type == "loader-1x1" then + elseif entity.type == "loader-1x1" or entity.type == "loader" then if not supports_cargo then local direction = entity.direction if is_ver then diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index 978893d8..8951e2d1 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -115,7 +115,7 @@ end ---@param map_data MapData ---@param stop LuaEntity ---@param comb1 LuaEntity ----@param comb2 LuaEntity +---@param comb2 LuaEntity? local function on_station_built(map_data, stop, comb1, comb2) --NOTE: only place where new Station local station = { @@ -285,10 +285,11 @@ local function on_combinator_built(map_data, comb) control.parameters = params end - map_data.to_comb[comb.unit_number] = comb - map_data.to_comb_params[comb.unit_number] = params - map_data.to_output[comb.unit_number] = out - map_data.to_stop[comb.unit_number] = stop + local unit_number = comb.unit_number--[[@as uint]] + map_data.to_comb[unit_number] = comb + map_data.to_comb_params[unit_number] = params + map_data.to_output[unit_number] = out + map_data.to_stop[unit_number] = stop if op == MODE_WAGON then if rail then @@ -328,41 +329,70 @@ local function on_combinator_built(map_data, comb) end end end + ---@param map_data MapData ---@param comb LuaEntity -function on_combinator_broken(map_data, comb) - --NOTE: we do not check for wagon manifest combinators and update their stations, it is assumed they will be lazy deleted later - ---@type uint - local comb_id = comb.unit_number - local out = map_data.to_output[comb_id] - local stop = map_data.to_stop[comb_id] - +---@param unit_number uint +---@return uint, uint, Station|Depot|Refueler|nil, LuaEntity? +--Returns the internal entity associated with the given combinator, if one exists. +--`unit_number` must be equal to `comb.unit_number`. +--Returns 1 if `comb` is `entity_comb1` of a station. +--Returns 2 if `comb` is `entity_comb2` of a station. +--Returns 3 if `comb` defines a depot. +--Returns 4 if `comb` defines a refueler. +--Returns 0 if `comb` is not a core component of any entity. +local function comb_to_internal_entity(map_data, comb, unit_number) + local stop = map_data.to_stop[unit_number] if stop and stop.valid then local id = stop.unit_number--[[@as uint]] local station = map_data.stations[id] if station then if station.entity_comb1 == comb then - on_station_broken(map_data, id, station) - on_stop_built_or_updated(map_data, stop, comb) + return 1, id, station, stop elseif station.entity_comb2 == comb then - station.entity_comb2 = search_for_station_combinator(map_data, stop, MODE_SECONDARY_IO, comb) + return 2, id, station, stop end else local depot = map_data.depots[id] if depot then if depot.entity_comb == comb then - on_depot_broken(map_data, id, depot) - on_stop_built_or_updated(map_data, stop, comb) + return 3, id, depot, stop end else local refueler = map_data.refuelers[id] - if refueler and refueler.entity_comb == comb then - on_refueler_broken(map_data, id, refueler) - on_stop_built_or_updated(map_data, stop, comb) + if refueler then + if refueler.entity_comb == comb then + return 4, id, refueler, stop + end end end end end + return 0, 0, nil, nil +end + +---@param map_data MapData +---@param comb LuaEntity +function on_combinator_broken(map_data, comb) + --NOTE: we do not check for wagon manifest combinators and update their stations, it is assumed they will be lazy deleted later + ---@type uint + local comb_id = comb.unit_number + local out = map_data.to_output[comb_id] + + local type, id, entity, stop = comb_to_internal_entity(map_data, comb, comb_id) + if type == 1 then + on_station_broken(map_data, id, entity--[[@as Station]]) + on_stop_built_or_updated(map_data, stop--[[@as LuaEntity]], comb) + elseif type == 2 then + local station = entity--[[@as Station]] + station.entity_comb2 = search_for_station_combinator(map_data, stop--[[@as LuaEntity]], MODE_SECONDARY_IO, comb) + elseif type == 3 then + on_depot_broken(map_data, id, entity--[[@as Depot]]) + on_stop_built_or_updated(map_data, stop--[[@as LuaEntity]], comb) + elseif type == 4 then + on_refueler_broken(map_data, id, entity--[[@as Refueler]]) + on_stop_built_or_updated(map_data, stop--[[@as LuaEntity]], comb) + end if out and out.valid then out.destroy() @@ -382,22 +412,19 @@ function combinator_update(map_data, comb, reset_display) local params = control.parameters local old_params = map_data.to_comb_params[unit_number] local has_changed = false - local station = nil - local id = nil - + local type, id, entity = nil, 0, nil - if params.operation == MODE_PRIMARY_IO_ACTIVE or params.operation == MODE_PRIMARY_IO_FAILED_REQUEST or params.operation == MODE_PRIMARY_IO then + local op = params.operation + --handle the combinator's display, if it is part of a station + if op == MODE_PRIMARY_IO or op == MODE_PRIMARY_IO_ACTIVE or op == MODE_PRIMARY_IO_FAILED_REQUEST then --the follow is only present to fix combinators that have been copy-pasted by blueprint with the wrong operation - local stop = map_data.to_stop[comb.unit_number--[[@as uint]]] - local should_reset = reset_display - if stop then - id = stop.unit_number--[[@as uint]] - station = map_data.stations[id] - if station and station.entity_comb1 ~= comb then - station = nil - end - if should_reset and station then - --make sure only MODE_PRIMARY_IO gets stored on map_data.to_comb_params + local set_control_params = true + + if reset_display then + type, id, entity = comb_to_internal_entity(map_data, comb, unit_number) + + if type == 1 then + local station = entity--[[@as Station]] if station.display_state == 0 then params.operation = MODE_PRIMARY_IO elseif station.display_state%2 == 1 then @@ -405,16 +432,17 @@ function combinator_update(map_data, comb, reset_display) else params.operation = MODE_PRIMARY_IO_FAILED_REQUEST end + set_control_params = false control.parameters = params - should_reset = false end end - if should_reset then - params.operation = MODE_PRIMARY_IO + --make sure only MODE_PRIMARY_IO gets stored on map_data.to_comb_params + params.operation = MODE_PRIMARY_IO + if set_control_params then control.parameters = params end - params.operation = MODE_PRIMARY_IO end + if params.operation ~= old_params.operation then --NOTE: This is rather dangerous, we may need to actually implement operation changing on_combinator_broken(map_data, comb) @@ -422,6 +450,7 @@ function combinator_update(map_data, comb, reset_display) interface_raise_combinator_changed(comb, old_params) return end + local new_signal = params.first_signal local old_signal = old_params.first_signal local new_network = new_signal and new_signal.name or nil @@ -429,54 +458,52 @@ function combinator_update(map_data, comb, reset_display) if new_network ~= old_network then has_changed = true - local stop = map_data.to_stop[comb.unit_number] - if stop and stop.valid then - if station then - --NOTE: these updates have to be queued to occur at tick init since central planning is expecting them not to change between ticks - if not map_data.queue_station_update then - map_data.queue_station_update = {} - end - map_data.queue_station_update[id] = true - else - local depot = map_data.depots[id] - if depot then - if depot.entity_comb == comb then - local train_id = depot.available_train_id - if train_id then - local train = map_data.trains[train_id] - remove_available_train(map_data, train_id, train) - add_available_train_to_depot(map_data, mod_settings, train_id, train, id, depot) - interface_raise_train_status_changed(train_id, STATUS_D, STATUS_D) - end - end - else - local refueler = map_data.refuelers[id] - if refueler and refueler.entity_comb == comb then - set_refueler_from_comb(map_data, mod_settings, id, refueler) - end - end + if type == nil then + type, id, entity = comb_to_internal_entity(map_data, comb, unit_number) + end + if type == 1 or type == 2 then + --NOTE: these updates have to be queued to occur at tick init since central planning is expecting them not to change between ticks + if not map_data.queue_station_update then + map_data.queue_station_update = {} end + map_data.queue_station_update[id] = true + elseif type == 3 then + local depot = entity--[[@as Depot]] + local train_id = depot.available_train_id + if train_id then + local train = map_data.trains[train_id] + remove_available_train(map_data, train_id, train) + add_available_train_to_depot(map_data, mod_settings, train_id, train, id, depot) + interface_raise_train_status_changed(train_id, STATUS_D, STATUS_D) + end + elseif type == 4 then + set_refueler_from_comb(map_data, mod_settings, id, entity--[[@as Refueler]]) end end + if params.second_constant ~= old_params.second_constant then has_changed = true - if station then + + if type == nil then + type, id, entity = comb_to_internal_entity(map_data, comb, unit_number) + end + --depots do not cache any combinator values so we don't have to update them here + if type == 1 or type == 2 then --NOTE: these updates have to be queued to occur at tick init since central planning is expecting them not to change between ticks if not map_data.queue_station_update then map_data.queue_station_update = {} end map_data.queue_station_update[id] = true - else - local refueler = map_data.refuelers[id] - if refueler then - local pre = refueler.allows_all_trains - set_refueler_from_comb(map_data, mod_settings, id, refueler) - if refueler.allows_all_trains ~= pre then - update_stop_if_auto(map_data, refueler, false) - end + elseif type == 4 then + local refueler = entity--[[@as Refueler]] + local pre = refueler.allows_all_trains + set_refueler_from_comb(map_data, mod_settings, id, refueler) + if refueler.allows_all_trains ~= pre then + update_stop_if_auto(map_data, refueler, false) end end end + if has_changed then map_data.to_comb_params[unit_number] = params interface_raise_combinator_changed(comb, old_params) diff --git a/dev/hr-cybernetic-displays.xcf b/dev/hr-cybernetic-displays.xcf new file mode 100644 index 00000000..72866733 Binary files /dev/null and b/dev/hr-cybernetic-displays.xcf differ