diff --git a/annotations/src/main/java/mindustry/annotations/impl/AssetsProcess.java b/annotations/src/main/java/mindustry/annotations/impl/AssetsProcess.java index 52706b508e..5ca28c0370 100644 --- a/annotations/src/main/java/mindustry/annotations/impl/AssetsProcess.java +++ b/annotations/src/main/java/mindustry/annotations/impl/AssetsProcess.java @@ -22,8 +22,8 @@ public class AssetsProcess extends BaseProcessor{ @Override public void process(RoundEnvironment env) throws Exception{ - processSounds("Sounds", rootDirectory + "/core/assets/sounds", "arc.audio.Sound"); - processSounds("Musics", rootDirectory + "/core/assets/music", "arc.audio.Music"); + processSounds("Sounds", rootDirectory + "/core/assets/sounds", "arc.audio.Sound", true); + processSounds("Musics", rootDirectory + "/core/assets/music", "arc.audio.Music", false); processUI(env.getElementsAnnotatedWith(StyleDefaults.class)); } @@ -117,25 +117,27 @@ public class AssetsProcess extends BaseProcessor{ JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer); } - void processSounds(String classname, String path, String rtype) throws Exception{ + void processSounds(String classname, String path, String rtype, boolean genid) throws Exception{ TypeSpec.Builder type = TypeSpec.classBuilder(classname).addModifiers(Modifier.PUBLIC); MethodSpec.Builder loadBegin = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC); CodeBlock.Builder staticb = CodeBlock.builder(); - type.addField(FieldSpec.builder(IntMap.class, "idToSound", Modifier.STATIC, Modifier.PRIVATE).initializer("new IntMap()").build()); - type.addField(FieldSpec.builder(ObjectIntMap.class, "soundToId", Modifier.STATIC, Modifier.PRIVATE).initializer("new ObjectIntMap()").build()); + if(genid){ + type.addField(FieldSpec.builder(IntMap.class, "idToSound", Modifier.STATIC, Modifier.PRIVATE).initializer("new IntMap()").build()); + type.addField(FieldSpec.builder(ObjectIntMap.class, "soundToId", Modifier.STATIC, Modifier.PRIVATE).initializer("new ObjectIntMap()").build()); - type.addMethod(MethodSpec.methodBuilder("getSoundId") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .addParameter(Sound.class, "sound") - .returns(int.class) - .addStatement("return soundToId.get(sound, -1)").build()); + type.addMethod(MethodSpec.methodBuilder("getSoundId") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addParameter(Sound.class, "sound") + .returns(int.class) + .addStatement("return soundToId.get(sound, -1)").build()); - type.addMethod(MethodSpec.methodBuilder("getSound") - .addModifiers(Modifier.PUBLIC, Modifier.STATIC) - .addParameter(int.class, "id") - .returns(Sound.class) - .addStatement("return (Sound)idToSound.get(id, () -> Sounds.none)").build()); + type.addMethod(MethodSpec.methodBuilder("getSound") + .addModifiers(Modifier.PUBLIC, Modifier.STATIC) + .addParameter(int.class, "id") + .returns(Sound.class) + .addStatement("return (Sound)idToSound.get(id, () -> Sounds.none)").build()); + } HashSet names = new HashSet<>(); Seq files = new Seq<>(); @@ -157,17 +159,23 @@ public class AssetsProcess extends BaseProcessor{ String filepath = path.substring(path.lastIndexOf("/") + 1) + p.path().substring(p.path().lastIndexOf(path) + path.length()); - staticb.addStatement("soundToId.put($L, $L)", name, id); + if(genid){ + staticb.addStatement("soundToId.put($L, $L)", name, id); - loadBegin.addStatement("$T.assets.load($S, $L.class).loaded = a -> { $L = ($L)a; soundToId.put(a, $L); idToSound.put($L, a); }", + loadBegin.addStatement("$T.assets.load($S, $L.class).loaded = a -> { $L = ($L)a; soundToId.put(a, $L); idToSound.put($L, a); }", Core.class, filepath, rtype, name, rtype, id, id); + }else{ + loadBegin.addStatement("$T.assets.load($S, $L.class).loaded = a -> { $L = ($L)a; }", Core.class, filepath, rtype, name, rtype); + } type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), name, Modifier.STATIC, Modifier.PUBLIC).initializer("new " + rtype + "()").build()); id ++; } - type.addStaticBlock(staticb.build()); + if(genid){ + type.addStaticBlock(staticb.build()); + } if(classname.equals("Sounds")){ type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), "none", Modifier.STATIC, Modifier.PUBLIC).initializer("new " + rtype + "()").build()); diff --git a/core/assets-raw/sprites/units/oct-cell.png b/core/assets-raw/sprites/units/oct-cell.png index 436242ed95..b27f93adb4 100644 Binary files a/core/assets-raw/sprites/units/oct-cell.png and b/core/assets-raw/sprites/units/oct-cell.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 94eaa3fb85..cebf19f21b 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -415,6 +415,7 @@ wavemode.health = health editor.default = [lightgray] details = Details... edit = Edit... +variables = Vars editor.name = Name: editor.spawn = Spawn Unit editor.removeunit = Remove Unit diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 2e80b91e2b..f9f694b71a 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -415,6 +415,7 @@ wavemode.health = vie editor.default = [lightgray] details = Détails... edit = Modifier... +variables = Vars editor.name = Nom : editor.spawn = Ajouter une unité editor.removeunit = Retirer l'unité @@ -1299,6 +1300,7 @@ block.plated-conduit.name = Conduit Plaqué block.phase-conduit.name = Conduit Phasé block.liquid-router.name = Routeur de Liquides block.liquid-tank.name = Réservoir à Liquides +block.liquid-container.name = Conteneur de liquide block.liquid-junction.name = Jonction à Liquides block.bridge-conduit.name = Pont à Liquide block.rotary-pump.name = Pompe Rotative @@ -1346,9 +1348,16 @@ block.silicon-crucible.name = Grande Fonderie de Silicium block.overdrive-dome.name = Dôme Accélérant block.interplanetary-accelerator.name = Accélérateur Interplanétaire #experimental, may be removed -block.block-forge.name = Forgeur de Blocs -block.block-loader.name = Chargeur de Blocs -block.block-unloader.name = Déchargeur de Blocs +block.constructor.name = Constructeur +block.constructor.description = Fabrique des structures d'une taille maximale de 2x2 (tuiles). +block.large-constructor.name = Grand Constructeur +block.large-constructor.description = Fabrique des structures d'une taille maximale de 4x4 (tuiles). +block.deconstructor.name = Déconstructeur +block.deconstructor.description = Déconstruit les structures et les unités. Retourne 100% du coût de construction. +block.payload-loader.name = Chargeur de charge utile +block.payload-loader.description = Chargez les liquides et les articles dans les blocs. +block.payload-unloader.name = Déchargeur de charge utile +block.payload-unloader.description = Décharge les liquides et les articles des blocs. block.switch.name = Interrupteur block.micro-processor.name = Micro Processeur @@ -1504,6 +1513,7 @@ block.conduit.description = Bloc de transport de liquide de base, faisant avance block.pulse-conduit.description = Conduit avancé permettant le transport de liquide. Transporte les liquides plus rapidement et en stocke plus que les conduits standards. block.plated-conduit.description = Déplace les liquides au même rythme que les conduits à impulsion, mais est renforcé et empêche les fuites en cas de rupture. N'accepte pas les liquides provenant des côtés, seuls les autres conduits peuvent le faire. block.liquid-router.description = Accepte les liquides depuis une direction et les distribue jusqu'à 3 directions équitablement. Utile pour envoyer un liquide à plusieurs endroits. Peut aussi stocker une certaine quantité de liquide. +block.liquid-container.description = Stocke une quantité considérable de liquide. Sort de tous les côtés, de la même manière qu'un routeur de liquide. block.liquid-tank.description = Stocke une grande quantité de liquide et peut les distribuer dans tous les côtés, un peu comme un routeur liquide.\nUtile pour réguler la demande en liquide si elle est inconstante ou comme sécurité pour refroidir des bâtiments importants. block.liquid-junction.description = Agit comme un pont pour deux conduits se croisant. Utile si deux conduits amènent différents liquides à différents endroits. block.bridge-conduit.description = Bloc de transport de liquide avancé permettant de traverser jusqu'à 3 blocs, au-dessus de n'importe quel terrain ou bâtiment. @@ -1769,6 +1779,7 @@ lenum.itemdrop = Lâche un objet. lenum.itemtake = Prend un objet depuis un bâtiment. lenum.paydrop = Lâche le chargement actuel. lenum.paytake = Prend un chargement à la position actuelle. +lenum.payenter = Entrez/atterrissez sur le bloc de charge utile sur lequel se trouve l'unité. lenum.flag = Drapeau numérique d'une unité. lenum.mine = Mine à une position donnée. lenum.build = Construit une structure. diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 8d6e617e0b..a542adc4b2 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1295,6 +1295,7 @@ block.plated-conduit.name = 도금된 파이프 block.phase-conduit.name = 메타 파이프 block.liquid-router.name = 액체 분배기 block.liquid-tank.name = 액체 탱크 +block.liquid-container.name = 액체 컨테이너 block.liquid-junction.name = 액체 교차기 block.bridge-conduit.name = 다리 파이프 block.rotary-pump.name = 동력 펌프 @@ -1341,10 +1342,16 @@ block.disassembler.name = 광재 분해기 block.silicon-crucible.name = 실리콘 도가니 block.overdrive-dome.name = 대형 과부하 프로젝터 block.interplanetary-accelerator.name = 성간 코어 가속기 -#experimental, may be removed / 이 아래의 블록들은 테스트용 임시 블록들이였습니다. -block.block-forge.name = 블록 제작대 -block.block-loader.name = 블록 로더 -block.block-unloader.name = 블록 언로더 +block.constructor.name = 제작대 +block.constructor.description = 최대 2x2 크기의 블록을 제작합니다. +block.large-constructor.name = 대형 제작대 +block.large-constructor.description = 최대 4x4 크기의 블록을 제작합니다. +block.deconstructor.name = 분해기 +block.deconstructor.description = 블록과 유닛을 분해합니다. 건설 비용의 100%를 돌려받습니다. +block.payload-loader.name = 블록 로더 +block.payload-loader.description = 들어간 블록에 액체와 아이템을 저장합니다. +block.payload-unloader.name = 블록 언로더 +block.payload-unloader.description = 들어간 블록에서 액체와 아이템을 가져옵니다. block.switch.name = 스위치 block.micro-processor.name = 마이크로 프로세서 @@ -1500,6 +1507,7 @@ block.conduit.description = 기본 액체 운송 블록. 액체를 앞으로 이 block.pulse-conduit.description = 고급 액체 운송 블록. 액체를 더 빠르게 운반하고 표준 파이프보다 더 많이 저장합니다. block.plated-conduit.description = 펄스 파이프와 같은 속도로 이동하지만 더 높은 방어력을 가지고 있습니다. 측면에서 액체들을 받아들이지 않습니다.\n액체가 누설하지 않습니다. block.liquid-router.description = 한 방향에서 액체를 받아 최대 3개의 다른 방향으로 같이 출력합니다. 일정량의 액체를 저장할 수도 있으며 한 소스에서 여러 대상으로 액체를 나누는 데 유용합니다. +block.liquid-container.description = 상당한 양의 액체를 저장합니다. 액체 라우터와 유사하게 모든 면에 출력할 수 있습니다. block.liquid-tank.description = 대량의 액체를 저장합니다. 재료가 일정하지 않은 상황에서 버퍼를 생성하거나 중요한 블록을 냉각하기 위한 보호 장치로 사용하세요. block.liquid-junction.description = 두 개의 교차 파이프를 위한 다리 역할을 합니다. 다른 액체를 다른 위치로 운반하는 두 개의 다른 파이프가 있는 상황에서 유용합니다. block.bridge-conduit.description = 고급 액체 운송 블록. 지형이나 건물을 넘어 최대 3개 타일 위로 액체를 운반할 수 있습니다. @@ -1765,6 +1773,7 @@ lenum.itemdrop = 아이템 투하 lenum.itemtake = 건물에서 아이템 수송 lenum.paydrop = 현재 화물 투하 lenum.paytake = 현재 위치에서 화물 수송 +lenum.payenter = 아래 화물 건물에 착륙 lenum.flag = 깃발 수 설정 lenum.mine = 특정 위치에서 채광 lenum.build = 구조물 건설 diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index efc43e7f74..6fd6d09df4 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -407,6 +407,7 @@ wavemode.health = всего прочности editor.default = [lightgray]<По умолчанию> details = Подробности… edit = Редактировать… +variables = Переменные editor.name = Название: editor.spawn = Создать боевую единицу editor.removeunit = Удалить боевую единицу @@ -1290,6 +1291,7 @@ block.plated-conduit.name = Укреплённый трубопровод block.phase-conduit.name = Фазовый трубопровод block.liquid-router.name = Жидкостный маршрутизатор block.liquid-tank.name = Жидкостный бак +block.liquid-container.name = Жидкостная цистерна block.liquid-junction.name = Жидкостный перекрёсток block.bridge-conduit.name = Мостовой трубопровод block.rotary-pump.name = Роторный насос @@ -1341,6 +1343,16 @@ block.block-forge.name = Завод блоков block.block-loader.name = Загрузчик блоков block.block-unloader.name = Разгрузчик блоков block.interplanetary-accelerator.name = Межпланетный ускоритель +block.constructor.name = Конструктор +block.constructor.description = Производит грузы размером 1x1 и 2x2 +block.large-constructor.name = Большой конструктор +block.large-constructor.description = Производит грузы размером 3x3 и 4x4 +block.deconstructor.name = Деконструктор +block.deconstructor.description = Разбирает грузы и боевые единицы с возвращением 100% использованных ресурсов на их производство +block.payload-loader.name = Грузовой загрузчик +block.payload-loader.description = Загружает жидкости и ресурсы в груз +block.payload-unloader.name = Грузовой разгрузчик +block.payload-unloader.description = Выгружает жидкости и ресурсы из груза block.switch.name = Переключатель block.micro-processor.name = Микропроцессор @@ -1496,6 +1508,7 @@ block.liquid-router.description = Принимает жидкости из од block.liquid-tank.description = Хранит большое количество жидкости. Выводит жидкости во все стороны, подобно жидкостному маршрутизатору. block.liquid-junction.description = Действует как мост для двух пересекающихся трубопроводов. block.bridge-conduit.description = Перемещает жидкости над любой местностью или зданиями. +block.liquid-container.description = Хранит большое количество жидкости. Выводит их во все стороны, как жидкостный маршрутизатор. block.phase-conduit.description = Перемещает жидкости над любой местностью или зданиями. Большая дистанция, чем у жидкостного моста, но требует энергию. block.power-node.description = Передает питание на подключенные узлы. Узел будет получать питание или поставлять питание на любые соседние блоки. block.power-node-large.description = Усовершенствованный силовой узел с большей дальностью. diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index b08fb30880..43705689d7 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -1294,6 +1294,7 @@ block.pulse-conduit.name = ท่อน้ำพัลซ์ block.plated-conduit.name = ท่อน้ำเสริมเกราะ block.phase-conduit.name = ท่อน้ำเฟส block.liquid-router.name = เร้าเตอร์ของเหลว +block.liquid-container.name = ตู้บรรจุของเหลว block.liquid-tank.name = ถังบรรจุของเหลว block.liquid-junction.name = ทางแยกของเหลว block.bridge-conduit.name = สะพานของเหลว @@ -1341,10 +1342,16 @@ block.disassembler.name = เครื่องถอดแยกส่วนป block.silicon-crucible.name = เบ้าหลอมซิลิคอน block.overdrive-dome.name = โดมเร่งประสิทธิภาพ block.interplanetary-accelerator.name = ฐานเร่งความเร็วระหว่างดาวเคราะห์ -#experimental, may be removed -block.block-forge.name = เครื่องสร้างบล็อก -block.block-loader.name = เครื่องโหลดบล็อก -block.block-unloader.name = เครื่องถ่ายบล็อก +block.constructor.name = เครื่องก่อสร้าง +block.constructor.description = สรรค์สร้างสิ่งก่อสร้างขนาดจนถึง 2x2 ช่อง +block.large-constructor.name = เครื่องก่อสร้างขนาดใหญ่ +block.large-constructor.description = สรรค์สร้างสิ่งก่อสร้างขนาดจนถึง 4x4 ช่อง +block.deconstructor.name = เครื่องลบทำลาย +block.deconstructor.description = ลบทำลายสิ่งก่อสร้างและยูนิต คืน 100% ของทรัพยากรที่ใช้ในการสร้าง +block.payload-loader.name = เครื่องโหลดสิ่งบรรทุก +block.payload-loader.description = โหลดของเหลวและไอเท็มเข้าไปในบล็อก +block.payload-unloader.name = เครื่องถ่ายสิ่งบรรทุก +block.payload-unloader.description = ถ่ายของเหลวและไอเท็มออกจากบล็อก block.switch.name = สวิตช์ block.micro-processor.name = ตัวประมวลผลขนาดเล็ก @@ -1445,7 +1452,7 @@ liquid.cryofluid.details = ของเหลวเฉื่อยและไ block.derelict =  [lightgray]ถูกทิ้งร้าง block.armored-conveyor.description = เลื่อนไอเท็มไปข้างหน้า เร็วเท่าสายพานไทเทเนี่ยม แต่มีเกราะที่แข็งแรงกว่า ไม่รับไอเท็มจากด้านข้างยกเว้นเป็นสายพานด้วยกันเอง -block.illuminator.description = ตัวเปล่งแสงขนาดกะทัดรัด ส่องสว่างในที่มืดได้ดี\nแถมยังกำหนดสีของแสงได้ด้วย... เจ๋งใช่มั้ยล่ะ +block.illuminator.description = ตัวเปล่งแสงขนาดกะทัดรัด ส่องสว่างในที่มืดได้ดี\nแถมยังกำหนดค่าสีของแสงได้ด้วย... เจ๋งใช่มั้ยล่ะ block.message.description = เก็บข้อความ ใช้สื่อสารกับพันธมิตร block.graphite-press.description = อัดก้อนถ่านหินให้เป็นแผ่นกราไฟต์บริสุทธิ์ block.multi-press.description = อัดก้อนถ่านหินให้เป็นแผ่นกราไฟต์บริสุทธิ์ ใช้น้ำและพลังงานในการแปรรูปถ่านหินให้เร็วและมีประสิทธิภาพมากขึ้น @@ -1515,13 +1522,14 @@ block.conduit.description = เคลื่อนย้ายของเหล block.pulse-conduit.description = เคลื่อนย้ายของเหลวไปข้างหน้า เคลื่อนย้ายได้เร็วขึ้นและเก็บของเหลวได้เยอะกว่าท่อน้ำธรรมดา block.plated-conduit.description = เคลื่อนย้ายของเหลวไปข้างหน้า ไม่รับของเหลวจากด้านข้างนอกจากท่อน้ำด้วยกันเอง\nไม่รั่ว และมีเกราะที่หนากว่า block.liquid-router.description = รับของเหลวจากทางเดียวแล้วส่งออกสามทางเท่าๆกัน สามารถเก็บของเหลวได้จำนวนหนึ่ง\nมีประโยชน์สำหรับการส่งของเหลวจากปั้มไปยังหลายที่ -block.liquid-tank.description = เก็บของเหลวจำนวนมาก ส่งออกไปรอบด้านคล้ายกับเร้าเตอร์ของเหลว\nใช้สำหรับสร้างกันชนในเวลาที่ของเหลวไม่คงที่หรือเวลาที่ใช้ของเหลว\nเป็นจำนวนมาก +block.liquid-container.description = เก็บของเหลวจำนวนปานกลาง ส่งออกไปรอบด้านคล้ายกับเร้าเตอร์ของเหลว\nเหมาะในการใช้กับเครื่องโหลดและถ่ายสิ่งบรรทุกสำหรับการขนส่งของเหลวทางไกล +block.liquid-tank.description = เก็บของเหลวจำนวนมาก ส่งออกไปรอบด้านคล้ายกับเร้าเตอร์ของเหลว\nเหมาะในการใช้เพื่อสร้างกันชนในเวลาที่ของเหลวไม่คงที่\nหรือเวลาที่ใช้ของเหลวเป็นจำนวนมาก block.liquid-junction.description = ทำหน้าที่เป็นสะพานสำหรับท่อน้ำสองท่อตัดกันที่มีของเหลวสองชนิดแล้วจะไปคนละที่ block.bridge-conduit.description = เคลื่อนย้ายของเหลวข้ามสิ่งก่อสร้างหรือกำแพง block.phase-conduit.description = เคลื่อนย้ายของเหลวข้ามสิ่งก่อสร้างหรือกำแพงด้วยความเร็วแสง\nมีระยะที่ไกลกว่าสะพานของเหลว แต่ต้องใช้พลังงาน block.power-node.description = ส่งพลังงานไปยังตัวจ่ายพลังงานที่เชื่อมต่อ ตัวจ่ายจะรับพลังงานจากตัวจ่ายอื่น\nหรือแหล่งพลังงานแล้วส่งไปยังบล็อกที่ติดกัน block.power-node-large.description = ตัวจ่ายพลังงานขั้นสูง มีระยะเชื่อมต่อกว้างขึ้น เชื่อมต่อได้มากขึ้น -block.surge-tower.description = ตัวจ่ายพลังงานที่มีระยะเชื่อมต่อไกลมากแต่เชื่อมต่อได้น้อย\nไว้ใช้สำหรับส่งพลังงานไปที่ไกลๆ +block.surge-tower.description = ตัวจ่ายพลังงานที่มีระยะเชื่อมต่อไกลมากแต่เชื่อมต่อได้น้อย\nเหมาะในการใช้เพื่อส่งพลังงานไปที่ไกลๆ block.diode.description = พลังงานแบตเตอรี่สามารถไหลผ่านบล็อกนี้ได้เพียงทางเดียว แต่เฉพาะเวลาที่อีกด้านมีพลังงานน้อยกว่าเท่านั้น block.battery.description = เก็บพลังงานเป็นกันชนเวลาที่มีพลังงานเกิน และส่งออกพลังงานเมื่อพลังงานไม่พอ block.battery-large.description = เก็บพลังงานเป็นกันชนเวลาที่มีพลังงานเกิน และส่งออกพลังงานเมื่อพลังงานไม่พอ\nเก็บพลังงานได้เยอะกว่าแบตเตอรี่ธรรมดา @@ -1781,6 +1789,7 @@ lenum.itemdrop = ปล่อยไอเท็ม lenum.itemtake = หยิบไอเท็มจากสิ่งก่อสร้าง lenum.paydrop = ปล่อยสิ่งที่บรรทุกอยู่ lenum.paytake = หยิบสิ่งบรรทุก ณ จุดที่อยู่ +lenum.payenter = เข้าไป/ลงจอดบนบล็อกบรรทุก ณ จุดที่ยูนิตอยู่ lenum.flag = ปักธงยูนิตเป็นหมายเลข lenum.mine = ขุดที่ตำแหน่งเป้าหมาย lenum.build = สร้างสิ่งก่อสร้าง diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 9db8f6eb97..aac3eca0de 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -168,8 +168,9 @@ planetmap = Gezegen Haritası launchcore = Kalkış filename = Dosya Adı: unlocked = Yeni içerik açıldı! -completed = [accent]Tamamlandı available = Yeni Araştırma Mümkün! +unlock.incampaign = < Detaylar için Mücadelede Araştır > +completed = [accent]Tamamlandı techtree = Teknoloji Ağacı research.legacy = [accent]5.0[] Araştırma Datası Bulnudu.\n[accent]Bu datayı Yüklemek ister misin?[], yoksa [accent]silip[] baştan mı başlamak istersin? (önerilir)? research.load = Yükle @@ -362,6 +363,7 @@ publish.confirm = Bunu yayınlamak istediğinize emin misiniz?\n[lightgray]önce publish.error = Nesneyi yayınlarken hata oluştu: {0} steam.error = Steam hatası.\nHata kodu: {0} +editor.cliffs = Duvardan Kayalığa editor.brush = Fırça editor.openin = Düzenleyici'de Aç editor.oregen = Maden Oluşumu @@ -377,6 +379,9 @@ editor.ingame = Oyun içinde düzenle editor.publish.workshop = Atölyede Yayınla editor.newmap = Yeni Harita editor.center = Ortala +editor.search = Harita Ara... +editor.filters = Harita Filtrele +editor.showAll = Varsayılan Haritaları Göster workshop = Atölye waves.title = Dalgalar waves.remove = Kaldır @@ -385,6 +390,7 @@ waves.waves = dalga(lar) waves.perspawn = doğma noktası başına waves.shields = kalkan/dalga waves.to = doğru +waves.max = maks birim waves.guardian = Gardiyan waves.preview = Önizleme waves.edit = Düzenle... @@ -409,6 +415,7 @@ wavemode.health = can editor.default = [lightgray] details = Detaylar... edit = Düzenle... +variables = Değişkenler editor.name = İsim: editor.spawn = Eleman Oluştur editor.removeunit = Eleman Kaldır @@ -657,10 +664,12 @@ status.sapped.name = Emilmiş status.electrified.name = Elektriklenmiş status.spore-slowed.name = Sporlanmış status.tarred.name = Ziftlenmiş +status.overdrive.name = Yüksek Hızlı status.overclock.name = Hızlandırlımış status.shocked.name = Çarpılmış status.blasted.name = Patlatılmış status.unmoving.name =Sabit +status.boss.name = Gardiyan settings.language = Dil settings.data = Oyun Verisi @@ -1124,6 +1133,7 @@ block.cliff.name = Uçurum block.sand-boulder.name = Kumlu Kaya Parçaları block.basalt-boulder.name = Bazalt Kaya block.grass.name = Çimen +block.pooled-cryofluid.name = Cryosıvı block.molten-slag.name = Cüruf block.space.name = Uzay block.salt.name = Tuz @@ -1284,6 +1294,7 @@ block.pulse-conduit.name = Dalga Borusu block.plated-conduit.name = Yalıtımlı Boru block.phase-conduit.name = Faz Borusu block.liquid-router.name = Sıvı Yönlendiricisi +block.liquid-container.name = Sıvı Konteyneri block.liquid-tank.name = Sıvı Tankı block.liquid-junction.name = Sıvı Kavşağı block.bridge-conduit.name = Köprülü Boru @@ -1331,9 +1342,16 @@ block.disassembler.name = Sökücü block.silicon-crucible.name = Büyük Silikon Fırını block.overdrive-dome.name = Hızlandırma Kubbesi #Düzgün tutun bu TR translatei uğraştırıyonuz beni. -RTOmega -block.block-forge.name = Blok Fabrikası -block.block-loader.name = Blok Yükleyici -block.block-unloader.name = Blok Boşaltıcı +block.constructor.name = İnşaatçı +block.constructor.description = 2x2 ve daha küçük blokları inşaa edebilir. +block.large-constructor.name = Büyük İnşaatçı +block.large-constructor.description = 4x4 ve daha küçük blokları inşaa edebilir. +block.deconstructor.name = Yıkıcı +block.deconstructor.description = Blok ve Birimleri yokeder, 100% iade sağlar. +block.payload-loader.name = Kargo Yükleyici +block.payload-loader.description = Sıvı ve malzemeleri bloklara yükler. +block.payload-unloader.name = Kargo Boşaltıcı +block.payload-unloader.description = Sıvı ve Malzemeleri bloklardan boşaltır. block.interplanetary-accelerator.name = Gezegenler Arası Hızlandırıcı #ama tüp ne aga -Anti Dragon block.switch.name = Düğme @@ -1489,6 +1507,7 @@ block.thermal-pump.description = En iyi pompa. Çalışması için enerji gereki block.conduit.description = Temel sıvı taşıma bloğu. Sıvıları ileri taşır. Pompalar ve diğer borularla birlikte kullanılır. block.pulse-conduit.description = Gelişmiş bir sıvı taşıma bloğu. Sıvıları normal borulardan daha hızlı taşır ve onlardan daha fazla sıvı alır. block.plated-conduit.description = Sıvıları dalga borusuyla aynı güçte taşır ancak daha fazla zırha sahiptir. Borular dışında başka bir şekilde yandan sıvı kabul etmez.\nDaha az sızıntı yapar. +block.liquid-container.description = Az bir miktarda sıvı depolar, her yöne dağıtır. block.liquid-router.description = Sıvıları bir yönden alıp diğer üç yöne eşit olarak dağıtır. Ayrıca kendisi de bir miktar sıvı depolayabilir. Sıvıları bir kaynaktan birden fazla hedefe iletmek için kullanılır. block.liquid-tank.description = Çok miktarda sıvıyı depolar. İhtiyaçları devamlı olmayan sıvıları yedek olarak saklamakta ya da önemli blokların devamlı olarak soğutulmasında kullanılabilir. block.liquid-junction.description = Çakışan iki boru hattı arasında bir köprü görevi görür. İki farklı borunun farklı hedeflere farklı sıvıları taşıdığı durumlarda kullanışlıdır. @@ -1594,7 +1613,7 @@ unit.eclipse.description = Büyük mermiler fırlatır ve lazer atar. unit.mono.description = Otomatik bir şekilde Bakır ve Kurşun kazar ve çekirdeğe getirir. unit.poly.description = Otomatik bir şekilde kırılmış binaları geri inşa eder ve oyuncuya inşaatta yardımcı olur. unit.mega.description = Otomayik bir şekilde hasarlı bolkları onarır. Blokları ve Birimleri taşıyabilir. -unit.quad.description = Büyük bombalar atar, hasarlı bolkları onarır ve düşmanlara zarar verir. Bolkları ve Birimleri taşıyabilir. +unit.quad.description = Büyük bombalar atar, hasarlı blokları onarır ve düşmanlara zarar verir. Bolkları ve Birimleri taşıyabilir. unit.oct.description = Yakındaki birimleri korur ve tamir eder. Blokları ve Birimleri taşıyabilir. unit.risso.description = Yakındaki düşmanlara Füze atar. unit.minke.description = Yakındaki düşmanlara basit mermi ve toplarla saldırır. @@ -1755,6 +1774,7 @@ lenum.itemdrop = Bir itemi bırak. lenum.itemtake = Bir binadan item al. lenum.paydrop = Kargoyu bırak. lenum.paytake = Kargo al. +lenum.payenter = Bir birimi, kargo tutabilen bir bloğa indir. lenum.flag = Numara ile işaretle. lenum.mine = Kaz. lenum.build = Bina inşa et. diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 1a2a9db84d..6923debf25 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -76,6 +76,7 @@ mods.browser.sortstars = Сортувати за популярністю stats = Статистика stat.wave = Хвиль відбито:[accent] {0} +stat.unitsCreated = Одиниць створено:[accent] {0} stat.enemiesDestroyed = Противників знищено:[accent] {0} stat.built = Будівель збудовано:[accent] {0} stat.destroyed = Будівель знищено:[accent] {0} @@ -83,7 +84,7 @@ stat.deconstructed = Будівель деконструйовано:[accent] {0 stat.delivered = Ресурсів запущено: stat.playtime = Час у грі:[accent] {0} stat.rank = Фінальний рахунок:[accent] {0} -globalitems = [accent]Усього предметів +globalitems = [accent]Усього ресурсів map.delete = Ви впевнені, що хочете видалити мапу «[accent]{0}[]»? level.highscore = Рекорд: [accent]{0} level.select = Вибір мапи @@ -91,6 +92,7 @@ level.mode = Режим гри: coreattack = < Ядро перебуває під атакою! > nearpoint = [[ [scarlet]ЗАЛИШТЕ ЗОНУ ВИСАДКИ НЕГАЙНО[] ]\nанігіляція неминуча database = База даних ядра +database.button = База даних savegame = Зберегти гру loadgame = Завантажити гру joingame = Мережева гра @@ -118,7 +120,7 @@ uploadingpreviewfile = Вивантаження файлу попередньо committingchanges = Здійснення змін done = Зроблено feature.unsupported = Ваш пристрій не підтримує цю функцію -mods.initfailed = [red]⚠[] Попереднього разу не вдалося ініціалізувати Mindustry. Це, ймовірно, було спричинено неправильними поведінкою модифікацій.\n\nДля запобігання нескінченним аварійним циклам [red]треба вимкнути всі модифікації.[]\n\nДля вимкнення цієї функції перейдіть до [accent]Налаштування→Гра→Вимикати модифікації після аварійного запуску[]. +mods.initfailed = [red]⚠[] Попереднього разу не вдалося ініціалізувати Mindustry. Це, ймовірно, було спричинено неправильними поведінкою модифікацій.\n\nДля запобігання нескінченним аварійним циклам [red]необхідно вимкнути всі модифікації.[]\n\nДля вимкнення цієї функції перейдіть до [accent]Налаштування→Гра→Вимикати модифікації після аварійного запуску[]. mods = Модифікації mods.none = [lightgray]Модифікацій не знайдено! mods.guide = Посібник із модифікацій @@ -164,6 +166,7 @@ launchcore = Запустити ядро filename = Назва файлу: unlocked = Доступний новий вміст! available = Нове дослідження доступно! +unlock.incampaign = < Розблокуйте в кампанії для отримання подробиць > completed = [accent]Завершено techtree = Дерево технологій research.legacy = Були знайдені дослідження з [accent]5.0[].\nЧи бажаєте ви [accent]завантажити ці дані[] або [accent]ви хочете відмовитися від цього[] і почати досліджувати із самого початку в новій кампанії (рекомендовано)? @@ -354,6 +357,7 @@ publishing = [accent]Публікація… publish.confirm = Ви дійсно хочете опублікувати це?\n\n[lightgray]Переконайтеся, що ви спочатку погоджуєтеся з EULA Майстерні, або ваші предмети не з’являться! publish.error = Виникла помилка під час публікації предмета: {0} steam.error = Не вдалося ініціалізувати сервіси Steam.\nПомилка: {0} +editor.cliffs = Стіни в скелі editor.brush = Пензлик editor.openin = Відкрити в редакторі editor.oregen = Генерація руд @@ -369,6 +373,9 @@ editor.ingame = Редагувати в грі editor.publish.workshop = Опублікувати в Майстерні Steam editor.newmap = Нова мапа editor.center = Центрувати +editor.search = Шукати мапи… +editor.filters = Фільтрувати мапи +editor.showAll = Показати вбудовані мапи workshop = Майстерня waves.title = Хвилі waves.remove = Видалити @@ -385,12 +392,20 @@ waves.load = Завантажити з буфера обміну waves.invalid = Недійсні хвилі в буфері обміну. waves.copied = Хвилі скопійовані. waves.none = Противники не були встановлені.\nЗазначимо, що пусті хвилі будуть автоматично замінені звичайною хвилею. +waves.sort = Сортування за +waves.sort.reverse = Зворотне сортування +waves.sort.begin = Хвилями +waves.sort.health = Здоров’ям +waves.sort.type = Типом +waves.units.hide = Сховати все +waves.units.show = Показати все wavemode.counts = кількість wavemode.totals = усього wavemode.health = здоров’я editor.default = [lightgray]<За замовчуванням> details = Подробиці… edit = Редагувати… +variables = Змінні editor.name = Ім’я: editor.spawn = Створити бойову одиницю editor.removeunit = Видалити бойову одиницю @@ -595,6 +610,8 @@ sector.biomassFacility.name = Центр дослідження синтезу sector.windsweptIslands.name = Вітряні острови sector.extractionOutpost.name = Видобувна застава sector.planetaryTerminal.name = Термінал планетарного запуску +sector.coastline.name = Узбережжя +sector.navalFortress.name = Морська фортеця sector.groundZero.description = Оптимальне місце для повторних ігор. Низька ворожа загроза. Мало ресурсів.\nЗберіть якомога більше свинцю та міді.\nНе затримуйтесь і йдіть далі. sector.frozenForest.description = Навіть тут, ближче до гір, уже поширилися спори. Холодна температура не змогла стримати їх назавжди.\n\nЗважтесь створити енергію. Побудуйте генератори внутрішнього згорання. Навчіться користуватися регенераторами. sector.saltFlats.description = На околицях пустелі лежать Соляні рівнини. У цьому місці небагато ресурсів.\n\nСаме тут противники спорудили комплекс зі зберігання ресурсів. Викорініть їхнє ядро. Не лишайте нічого цінного. @@ -621,6 +638,7 @@ status.sapped.name = Виснажений status.electrified.name = Наелектризований status.spore-slowed.name = Сповільнений спорами status.tarred.name = Покритий нафтою +status.overdrive.name = Перевантажений status.overclock.name = Прискорений status.shocked.name = Шокований status.blasted.name = Підірваний @@ -1076,6 +1094,7 @@ block.sand-boulder.name = Пісочний валун block.basalt-boulder.name = Базальтовий валун block.grass.name = Трава block.molten-slag.name = Шлак +block.pooled-cryofluid.name = Кріогенна рідина block.space.name = Космос block.salt.name = Сіль block.salt-wall.name = Соляна стіна @@ -1109,6 +1128,7 @@ block.core-nucleus.name = Ядро «Атом» block.deep-water.name = Глибоководдя block.shallow-water.name = Вода block.tainted-water.name = Забруднена вода +block.deep-tainted-water.name = Забруднене глибоководдя block.darksand-tainted-water.name = Темний пісок із забрудненою водою block.tar.name = Дьоготь block.stone.name = Камінь @@ -1230,12 +1250,13 @@ block.solar-panel.name = Сонячна панель block.solar-panel-large.name = Велика сонячна панель block.oil-extractor.name = Екстрактор нафти block.repair-point.name = Ремонтний пункт -block.repair-point.name = Ремонтна башта +block.repair-turret.name = Ремонтна башта block.pulse-conduit.name = Імпульсний трубопровід block.plated-conduit.name = Зміцнений трубопровід block.phase-conduit.name = Фазовий трубопровід block.liquid-router.name = Рідинний маршрутизатор block.liquid-tank.name = Рідинний резервуар +block.liquid-container.name = Рідинний контейнер block.liquid-junction.name = Рідинне перехрестя block.bridge-conduit.name = Мостовий трубопровід block.rotary-pump.name = Роторний насос @@ -1282,9 +1303,17 @@ block.disassembler.name = Розбирач block.silicon-crucible.name = Кремнієвий тигель block.overdrive-dome.name = Великий прискорювач block.interplanetary-accelerator.name = Міжпланетний прискорювач -block.block-forge.name = Блок-кузня -block.block-loader.name = Блок-завантажувач -block.block-unloader.name = Блок-вивантажувач +block.constructor.name = Конструктор +block.constructor.description = Збирає споруди. Доступні розміри для збирання: 1x1, 2x2. +block.large-constructor.name = Великий конструктор +block.large-constructor.description = Збирає споруди. Доступні розміри для збирання: 1x1, 2x2, 3x3 та 4x4. +block.deconstructor.name = Деконструктор +block.deconstructor.description = Деконструює споруди та одиниці. Повертає 100% вартості збірки. +block.payload-loader.name = Вантажний завантажувач +block.payload-loader.description = Завантажує рідини та предмети в блоки. +block.payload-unloader.name = Вантажний розвантажувач +block.payload-unloader.description = Розвантажує рідини та предмети в блоки. + block.switch.name = Перемикач block.micro-processor.name = Мікропроцесор block.logic-processor.name = Логічний процесор @@ -1316,7 +1345,7 @@ hint.placeConveyor.mobile = Конвеєри переміщують предме hint.placeTurret = Розмістіть  [accent]башти[], щоби захистити базу від ворогів.\n\nБашти потребують боєприпасів. У цьому випадку \uf838мідь.\nДля її подачі використовуйте конвеєри та бури. hhint.breaking = Натисніть [accent]ПКМ[] і тягніть, щоби зруйнувати блоки. hint.breaking.mobile = Активуйте  [accent]молот[] внизу праворуч і торкніться блоків, щоби їх розібрати.\n\nУтримуйте палець протягом секунди і протягніть, щоби розібрати виділене. -hint.blockInfo = Подивіться інформацію про блок. Перейдіть до [accent]меню будівництва[] і натисніть на кнопку [accent][[?][] правпоруч +hint.blockInfo = Подивіться інформацію про блок. Перейдіть до [accent]меню будівництва[] і натисніть на кнопку [accent][[?][] праворуч. hint.research = Використовуйте кнопку  [accent]Дослідження[] для дослідження нової технології. hint.derelict = Будівлі [accent]Переможених[] є зламаними залишками старих баз, які більше не функціонують.\n\nЇх можна [accent]деконструювати[] для отримання ресурсів. hint.research.mobile = Використовуйте  [accent]Дослідження[] в  [accent]меню[] для дослідження нової технології. @@ -1339,12 +1368,13 @@ hint.generator =  [accent]Генератори внутрішнього зг hint.guardian = [accent]Вартові[] одиниці броньовані. Слабкі боєприпаси, як-от [accent]мідь[] чи [accent]свинець[], [scarlet]не є ефективними[].\n\nВикористовуйте башти вищого рангу чи  [accent]графітові боєприпаси[] для Подвійної башти чиЗалпу, щоб убити Вартових. hint.coreUpgrade = Ядро можна покращити, якщо [accent]розмістити поверх нього ядро вищого рівня[].\n\nРозмістіть  ядро [accent]«Штаб»[] поверх  ядра [accent]«Уламок»[]. Переконайтесь, що поблизу ядер немає перешкод (зайвих блоків). hint.presetLaunch = Сірі [accent]сектори зони посадки[], як-от [accent]Крижаний ліс[], можна запустити з будь-якого місця. Вони не вимагають захоплення сусідньої території.\n\n[accent]Нумеровані сектори[], як цей, [accent]необовʼязкові[]. +hint.presetDifficulty = Цей сектор має [scarlet]високий рівень ворожої загрози[].\nРобити запуск в такі [accent]не рекомендується[] без належних технологій та підготовки. hint.coreIncinerate = Після того, як ядро наповниться предметом, будь-які додаткові предмети того ж типу, які воно отримує, будуть [accent]спалені[]. item.copper.description = Використовується у всіх типах блоків і боєприпасах. item.copper.details = Мідь. Напрочуд багато жил цієї руди на Серпуло. За своєю структурою слабка, якщо не зміцнена. item.lead.description = Широко використовується в електроніці та в транспортуванні рідин. -item.lead.details = Сплав. Інертний. Широко використовується в акумуляторах.\nПримітка. Мабуть, токсичний для біологічних форм життя. Не те щоби тут залишилося багато… +item.lead.details = Інертний сплав, що широко використовується в акумуляторах.\nПримітка. Мабуть, токсичний для біологічних форм життя. Не те щоби їх тут залишилося багато… item.metaglass.description = Використовується для розподілу чи зберігання рідини. item.graphite.description = Використовується для боєприпасів та електричних компонентів. item.sand.description = Використовується для виробництва інших удосконалених матеріалів. @@ -1432,6 +1462,7 @@ block.conduit.description = Пересуває рідини вперед. Зас block.pulse-conduit.description = Пересуває рідини вперед. Швидше транспортує і зберігає більше рідини, ніж стандартні трубопроводи. block.plated-conduit.description = Пересуває рідини вперед. Не приймає рідин із боків окрім інших трубопроводів. Не протікає. block.liquid-router.description = Приймає рідини з одного напрямку та виводить їх до трьох інших напрямків порівну. Також може зберігати певну кількість рідини. +block.liquid-container.description = Зберігає чималу кількість рідини. Виводить у всі сторони, подібно до рідинного маршрутизатора. block.liquid-tank.description = Зберігає велику кількість рідини. Виводить воду на всі сторони, через це схожий на рідинний маршрутизатор. block.liquid-junction.description = Діє як міст для двох трубопроводів. block.bridge-conduit.description = Транспортує рідину через місцевість і будівлі. @@ -1484,7 +1515,7 @@ block.cyclone.description = Підпалює вибухові грудки ск block.spectre.description = Вистрілює великі бронебійні кулі в повітряні та наземні цілі. block.meltdown.description = Заряджає і вистрілює лазерним променем у найближчих противників. Для роботи потрібен теплоносій. block.foreshadow.description = Вистрілює великим болтом в одну ціль на велику дистанцію. -block.repair-point.description = Безперервно ремонтує найближчу пошкоджену бойову одиницю у своєму радіусі дії. Пріоритетні вороги з вищим максимальним здоров’ям. +block.repair-point.description = Безперервно ремонтує найближчу пошкоджену бойову одиницю у своєму радіусі дії. Пріоритетні союзники з вищим максимальним здоров’ям. block.segment.description = Пошкоджує та руйнує вхідні снаряди. Окрім лазерних. block.parallax.description = Притягає ворожі повітряні одиниці, пошкоджуючи їх у процесі. block.tsunami.description = Вистрілює потужними потоками рідини у ворогів. Автоматично гасить пожежі в разі постачання води. @@ -1545,7 +1576,7 @@ unit.omura.description = Вистрілює у ворогів далекобій unit.alpha.description = Захищає ядро «Уламок» від противників. Будує споруди. unit.beta.description = Захищає ядро «Штаб» від противників. Будує споруди. unit.gamma.description = Захищає ядро «Атом» від противників. Будує споруди. -unit.retusa.description = Розміщує міни. Ремонтує найближчі одиниці. +unit.retusa.description = Вистрілює самонаведеними торпедами по ворогах. Ремонтує найближчі одиниці. unit.oxynoe.description = Вистрілює потоками полум'я, яке ремонтує споруди та наносить шкоду ворогам. Захищає від ворожик снарядів за допомогою башти точкової оборони. unit.cyerce.description = Вистрілює у ворогів навідними касетними ракетами. Ремонтує найближчі одиниці. unit.aegires.description = Приголомшлює ворожі одиниці та будівлі, що входять до його енергетичного поля. Ремонтує всіх союзників. @@ -1565,8 +1596,8 @@ lst.sensor = Отримати дані з певної будівлі чи од lst.set = Установити значення змінної. lst.operation = Виконує операцію над 1-2 змінними. lst.end = Перейти до верхньої частини стеку операцій. -lst.wait = Зачекати певну кількість секунд. -lst.lookup = Знайдіть тип елемента, рідини, одиниці чи блоку за ідентифікатором.\nМожна отримати доступ до загальної кількості кожного типу через \n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] +lst.wait = Чекати певну кількість секунд. +lst.lookup = Знайти тип елемента, рідини, одиниці чи блоку за ідентифікатором.\nМожна отримати доступ до загальної кількості кожного типу через \n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[] lst.jump = Умовне переходження до іншої операції. lst.unitbind = Прив’язка до одиниці певного типу та його зберігання в [accent]@unit[]. lst.unitcontrol = Контролювати поточну прив’язану одиницю. @@ -1694,6 +1725,7 @@ lenum.itemdrop = Викинути предмет. lenum.itemtake = Взяти предмет з будівлі. lenum.paydrop = Скинути поточний вантаж. lenum.paytake = Підібрати вантаж у поточному місцерозташуванні. +lenum.payenter = Увійти чи вийти з вантажного блока, над яким перебуває одиниця. lenum.flag = Числовий флаг одиниці. lenum.mine = Видобувати у заданій позиції. lenum.build = Побудувати будівлю. diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 3034d4e228..48458937a4 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -26,6 +26,7 @@ import mindustry.maps.*; import mindustry.mod.*; import mindustry.net.*; import mindustry.service.*; +import mindustry.world.*; import java.io.*; import java.nio.charset.*; @@ -195,6 +196,8 @@ public class Vars implements Loadable{ public static Fi launchIDFile; /** empty map, indicates no current map */ public static Map emptyMap; + /** empty tile for payloads */ + public static Tile emptyTile; /** map file extension */ public static final String mapExtension = "msav"; /** save file extension */ @@ -310,6 +313,10 @@ public class Vars implements Loadable{ modDirectory.mkdirs(); + Events.on(ContentInitEvent.class, e -> { + emptyTile = new Tile(Short.MAX_VALUE - 20, Short.MAX_VALUE - 20); + }); + mods.load(); maps.load(); } diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index 1a7ae2b1ec..b2567d31cc 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -23,7 +23,7 @@ public class Planets implements ContentList{ @Override public void load(){ - sun = new Planet("sun", null, 4){{ + sun = new Planet("sun", null, 4f){{ bloom = true; accessible = false; @@ -40,7 +40,7 @@ public class Planets implements ContentList{ ); }}; - erekir = new Planet("erekir", sun, 1, 2){{ + erekir = new Planet("erekir", sun, 1f, 2){{ generator = new ErekirPlanetGenerator(); meshLoader = () -> new HexMesh(this, 5); atmosphereColor = Color.valueOf("f07218"); @@ -71,7 +71,7 @@ public class Planets implements ContentList{ gen.max += 2; }); - tantros = new Planet("tantros", sun, 1, 2){{ + tantros = new Planet("tantros", sun, 1f, 2){{ generator = new TantrosPlanetGenerator(); meshLoader = () -> new HexMesh(this, 4); atmosphereColor = Color.valueOf("3db899"); @@ -81,7 +81,7 @@ public class Planets implements ContentList{ alwaysUnlocked = true; }}; - serpulo = new Planet("serpulo", sun, 1, 3){{ + serpulo = new Planet("serpulo", sun, 1f, 3){{ generator = new SerpuloPlanetGenerator(); meshLoader = () -> new HexMesh(this, 6); cloudMeshLoader = () -> new MultiMesh( diff --git a/core/src/mindustry/content/TechTree.java b/core/src/mindustry/content/TechTree.java index cfd69fb61d..e182a0ce4c 100644 --- a/core/src/mindustry/content/TechTree.java +++ b/core/src/mindustry/content/TechTree.java @@ -88,7 +88,9 @@ public class TechTree implements ContentList{ node(conduit, () -> { node(liquidJunction, () -> { node(liquidRouter, () -> { - node(liquidTank); + node(liquidContainer, () -> { + node(liquidTank); + }); node(bridgeConduit); diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 5db02f47e4..6eb1612d13 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -587,6 +587,7 @@ public class UnitTypes implements ContentList{ ammoType = new ItemAmmoType(Items.coal); weapons.add(new Weapon(){{ + shootOnDeath = true; reload = 24f; shootCone = 180f; ejectEffect = Fx.none; @@ -597,7 +598,7 @@ public class UnitTypes implements ContentList{ hitEffect = Fx.pulverize; lifetime = 10f; speed = 1f; - splashDamageRadius = 60f; + splashDamageRadius = 55f; instantDisappear = true; splashDamage = 90f; killShooter = true; diff --git a/core/src/mindustry/entities/comp/BlockUnitComp.java b/core/src/mindustry/entities/comp/BlockUnitComp.java index a0b1fdebcd..39adf5c891 100644 --- a/core/src/mindustry/entities/comp/BlockUnitComp.java +++ b/core/src/mindustry/entities/comp/BlockUnitComp.java @@ -18,7 +18,7 @@ abstract class BlockUnitComp implements Unitc{ //sets up block stats maxHealth(tile.block.health); - health(tile.health()); + health(tile.health); hitSize(tile.block.size * tilesize * 0.7f); set(tile); } diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index f558443880..923964163e 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -291,7 +291,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } public byte relativeTo(Building tile){ - return relativeTo(tile.tile()); + return relativeTo(tile.tile); } public byte relativeToEdge(Tile other){ @@ -413,25 +413,28 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } - public void handleUnitPayload(Unit player, Cons grabber){ - Fx.spawn.at(player); + public void handleUnitPayload(Unit unit, Cons grabber){ + Fx.spawn.at(unit); - if(player.isPlayer()){ - player.getPlayer().clearUnit(); + if(unit.isPlayer()){ + unit.getPlayer().clearUnit(); } - player.remove(); - grabber.get(new UnitPayload(player)); - Fx.unitDrop.at(player); - if(Vars.net.client()){ - Vars.netClient.clearRemovedEntity(player.id); - } + unit.remove(); + //needs new ID as it is now a payload + unit.id = EntityGroup.nextId(); + grabber.get(new UnitPayload(unit)); + Fx.unitDrop.at(unit); } public boolean canUnload(){ return block.unloadable; } + public boolean payloadCheck(int conveyorRotation){ + return block.rotate && (rotation + 2) % 4 == conveyorRotation; + } + /** Called when an unloader takes an item. */ public void itemTaken(Item item){ @@ -920,6 +923,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, drawTeamTop(); } + public void payloadDraw(){ + draw(); + } + public void drawTeamTop(){ if(block.teamRegion.found()){ if(block.teamRegions[team.id] == block.teamRegion) Draw.color(team.color); @@ -971,6 +978,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } } + /** @return whether this building is in a payload */ + public boolean isPayload(){ + return tile == emptyTile; + } + /** * Called when a block is placed over some other blocks. This seq will always have at least one item. * Should load some previous state, if necessary. */ @@ -1059,7 +1071,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, for(int i = 0; i < Mathf.clamp(amount / 5, 0, 30); i++){ Time.run(i / 2f, () -> { - Tile other = world.tile(tileX() + Mathf.range(block.size / 2), tileY() + Mathf.range(block.size / 2)); + Tile other = world.tileWorld(x + Mathf.range(block.size * tilesize / 2), y + Mathf.range(block.size * tilesize / 2)); if(other != null){ Puddles.deposit(other, liquid, splash); } diff --git a/core/src/mindustry/entities/comp/LegsComp.java b/core/src/mindustry/entities/comp/LegsComp.java index 81073abc1f..f147217c57 100644 --- a/core/src/mindustry/entities/comp/LegsComp.java +++ b/core/src/mindustry/entities/comp/LegsComp.java @@ -36,7 +36,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{ @Override @Replace public int pathType(){ - return type.allowLegStep ? Pathfinder.costGround : Pathfinder.costLegs; + return type.allowLegStep ? Pathfinder.costLegs : Pathfinder.costGround; } @Override diff --git a/core/src/mindustry/entities/comp/PayloadComp.java b/core/src/mindustry/entities/comp/PayloadComp.java index 3cc63c835d..fc22eff425 100644 --- a/core/src/mindustry/entities/comp/PayloadComp.java +++ b/core/src/mindustry/entities/comp/PayloadComp.java @@ -61,6 +61,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{ void pickup(Building tile){ tile.pickedUp(); tile.tile.remove(); + tile.tile = Vars.emptyTile; payloads.add(new BuildPayload(tile)); Fx.unitPickup.at(tile); Events.fire(new PickupEvent(self(), tile)); diff --git a/core/src/mindustry/game/Saves.java b/core/src/mindustry/game/Saves.java index 298d9a48ed..870d5a9634 100644 --- a/core/src/mindustry/game/Saves.java +++ b/core/src/mindustry/game/Saves.java @@ -155,6 +155,7 @@ public class Saves{ SaveSlot slot = new SaveSlot(getNextSlotFile()); slot.importFile(file); slot.setName(file.nameWithoutExtension()); + saves.add(slot); slot.meta = SaveIO.getMeta(slot.file); current = slot; @@ -330,6 +331,10 @@ public class Saves{ public void importFile(Fi from) throws IOException{ try{ from.copyTo(file); + if(previewFile().exists()){ + requestedPreview = false; + previewFile().delete(); + } }catch(Exception e){ throw new IOException(e); } diff --git a/core/src/mindustry/game/Waves.java b/core/src/mindustry/game/Waves.java index 848b4ecf96..462d8eba87 100644 --- a/core/src/mindustry/game/Waves.java +++ b/core/src/mindustry/game/Waves.java @@ -285,7 +285,7 @@ public class Waves{ if(naval){ species = Structs.filter(UnitType[].class, species, v -> v[0].flying || v[0].naval); }else{ - species = Structs.filter(UnitType[].class, species, v -> v[0].flying && !v[0].naval); + species = Structs.filter(UnitType[].class, species, v -> !v[0].naval); } UnitType[][] fspec = species; diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index 01e6782497..9004508f15 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -335,7 +335,7 @@ public class LExecutor{ /** Checks is a unit is valid for logic AI control, and returns the controller. */ @Nullable public static LogicAI checkLogicAI(LExecutor exec, Object unitObj){ - if(unitObj instanceof Unit unit && exec.obj(varUnit) == unit && unit.team == exec.team && !unit.isPlayer() && !(unit.controller() instanceof FormationAI)){ + if(unitObj instanceof Unit unit && unit.isValid() && exec.obj(varUnit) == unit && unit.team == exec.team && !unit.isPlayer() && !(unit.controller() instanceof FormationAI)){ if(unit.controller() instanceof LogicAI la){ la.controller = exec.building(varThis); return la; @@ -934,27 +934,31 @@ public class LExecutor{ //this should avoid any garbage allocation Var v = exec.var(value); if(v.isobj && value != 0){ - String strValue = - v.objval == null ? "null" : - v.objval instanceof String s ? s : - v.objval == Blocks.stoneWall ? "solid" : //special alias - v.objval instanceof MappableContent content ? content.name : - v.objval instanceof Content ? "[content]" : - v.objval instanceof Building build ? build.block.name : - v.objval instanceof Unit unit ? unit.type.name : - v.objval instanceof Enum e ? e.name() : - "[object]"; + String strValue = toString(v.objval); exec.textBuffer.append(strValue); }else{ //display integer version when possible - if(Math.abs(v.numval - (long)v.numval) < 0.000001){ + if(Math.abs(v.numval - (long)v.numval) < 0.00001){ exec.textBuffer.append((long)v.numval); }else{ exec.textBuffer.append(v.numval); } } } + + public static String toString(Object obj){ + return + obj == null ? "null" : + obj instanceof String s ? s : + obj == Blocks.stoneWall ? "solid" : //special alias + obj instanceof MappableContent content ? content.name : + obj instanceof Content ? "[content]" : + obj instanceof Building build ? build.block.name : + obj instanceof Unit unit ? unit.type.name : + obj instanceof Enum e ? e.name() : + "[object]"; + } } public static class PrintFlushI implements LInstruction{ diff --git a/core/src/mindustry/logic/LogicDialog.java b/core/src/mindustry/logic/LogicDialog.java index c34f5347ba..6331d4031a 100644 --- a/core/src/mindustry/logic/LogicDialog.java +++ b/core/src/mindustry/logic/LogicDialog.java @@ -2,9 +2,16 @@ package mindustry.logic; import arc.*; import arc.func.*; +import arc.graphics.*; +import arc.scene.actions.*; +import arc.scene.ui.*; import arc.scene.ui.TextButton.*; import arc.util.*; +import mindustry.core.GameState.*; +import mindustry.ctype.*; import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.logic.LExecutor.*; import mindustry.logic.LStatements.*; import mindustry.ui.*; import mindustry.ui.dialogs.*; @@ -15,6 +22,7 @@ import static mindustry.logic.LCanvas.*; public class LogicDialog extends BaseDialog{ public LCanvas canvas; Cons consumer = s -> {}; + @Nullable LExecutor executor; public LogicDialog(){ super("logic"); @@ -57,6 +65,90 @@ public class LogicDialog extends BaseDialog{ dialog.show(); }).name("edit"); + buttons.button("@variables", Icon.menu, () -> { + BaseDialog dialog = new BaseDialog("@variables"); + dialog.hidden(() -> { + if(!wasPaused){ + state.set(State.paused); + } + }); + + dialog.shown(() -> { + if(!wasPaused){ + state.set(State.playing); + } + }); + + dialog.cont.pane(p -> { + p.margin(10f).marginRight(16f); + p.table(Tex.button, t -> { + t.defaults().fillX().height(45f); + for(var s : executor.vars){ + if(s.constant) continue; + + Color varColor = Pal.gray; + float stub = 8f, mul = 0.5f, pad = 4; + + Color color = + !s.isobj ? Pal.place : + s.objval == null ? Color.darkGray : + s.objval instanceof String ? Pal.ammo : + s.objval instanceof Content ? Pal.logicOperations : + s.objval instanceof Building ? Pal.logicBlocks : + s.objval instanceof Unit ? Pal.logicUnits : + s.objval instanceof Enum ? Pal.logicIo : + Color.white; + + String typeName = + !s.isobj ? "number" : + s.objval == null ? "null" : + s.objval instanceof String ? "string" : + s.objval instanceof Content ? "content" : + s.objval instanceof Building ? "building" : + s.objval instanceof Unit ? "unit" : + s.objval instanceof Enum ? "enum" : + "unknown"; + + t.add(new Image(Tex.whiteui, varColor.cpy().mul(mul))).width(stub); + t.stack(new Image(Tex.whiteui, varColor), new Label(" " + s.name + " ", Styles.outlineLabel){{ + setColor(Pal.accent); + }}).padRight(pad); + + t.add(new Image(Tex.whiteui, Pal.gray.cpy().mul(mul))).width(stub); + t.table(Tex.pane, out -> { + float period = 15f; + float[] counter = {-1f}; + Label label = out.add("").style(Styles.outlineLabel).padLeft(4).padRight(4).width(140f).wrap().get(); + label.update(() -> { + if(counter[0] < 0 || (counter[0] += Time.delta) >= period){ + String text = s.isobj ? PrintI.toString(s.objval) : Math.abs(s.numval - (long)s.numval) < 0.00001 ? (long)s.numval + "" : s.numval + ""; + if(!label.textEquals(text)){ + label.setText(text); + if(counter[0] >= 0f){ + label.actions(Actions.color(Pal.accent), Actions.color(Color.white, 0.2f)); + } + } + counter[0] = 0f; + } + }); + label.act(1f); + }).padRight(pad); + + //TODO type name does not update, is this important? + t.add(new Image(Tex.whiteui, color.cpy().mul(mul))).width(stub); + t.stack(new Image(Tex.whiteui, color), new Label(" " + typeName + " ", Styles.outlineLabel)); + + t.row(); + + t.add().growX().colspan(6).height(4).row(); + } + }); + }); + + dialog.addCloseButton(); + dialog.show(); + }).name("variables").disabled(b -> executor == null || executor.vars.length == 0); + buttons.button("@add", Icon.add, () -> { BaseDialog dialog = new BaseDialog("@add"); dialog.cont.pane(t -> { @@ -92,7 +184,8 @@ public class LogicDialog extends BaseDialog{ onResize(() -> canvas.rebuild()); } - public void show(String code, Cons modified){ + public void show(String code, LExecutor executor, Cons modified){ + this.executor = executor; canvas.statements.clearChildren(); canvas.rebuild(); try{ diff --git a/core/src/mindustry/service/GameService.java b/core/src/mindustry/service/GameService.java index a3890b6fc6..76c647c250 100644 --- a/core/src/mindustry/service/GameService.java +++ b/core/src/mindustry/service/GameService.java @@ -176,7 +176,7 @@ public class GameService{ }); Events.on(UnitControlEvent.class, e -> { - if(e.unit instanceof BlockUnitc && ((BlockUnitc)e.unit).tile().block == Blocks.router){ + if(e.unit instanceof BlockUnitc unit && unit.tile().block == Blocks.router){ becomeRouter.complete(); } }); diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index adfc406768..31a392c613 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -132,6 +132,12 @@ public class Planet extends UnlockableContent{ } } + /** @deprecated confusing parameter orer, use the other constructor instead */ + @Deprecated + public Planet(String name, Planet parent, int sectorSize, float radius){ + this(name, parent, radius, sectorSize); + } + public @Nullable Sector getLastSector(){ if(sectors.isEmpty()){ return null; diff --git a/core/src/mindustry/ui/dialogs/BaseDialog.java b/core/src/mindustry/ui/dialogs/BaseDialog.java index b99b164ca4..3087addd32 100644 --- a/core/src/mindustry/ui/dialogs/BaseDialog.java +++ b/core/src/mindustry/ui/dialogs/BaseDialog.java @@ -11,7 +11,7 @@ import mindustry.graphics.*; import static mindustry.Vars.*; public class BaseDialog extends Dialog{ - private boolean wasPaused; + protected boolean wasPaused; protected boolean shouldPause; public BaseDialog(String title, DialogStyle style){ diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index feaf234ae9..7c1b5936a4 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -50,6 +50,7 @@ public class Block extends UnlockableContent{ public boolean outputsPayload = false; public boolean acceptsPayload = false; public boolean acceptsItems = false; + public boolean separateItemCapacity = false; public int itemCapacity = 10; public float liquidCapacity = 10f; diff --git a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java index 8106aa836a..1f80bb26fc 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/LaserTurret.java @@ -106,7 +106,7 @@ public class LaserTurret extends PowerTurret{ @Override protected void bullet(BulletType type, float angle){ - bullet = type.create(tile.build, team, x + tr.x, y + tr.y, angle); + bullet = type.create(this, team, x + tr.x, y + tr.y, angle); bulletLife = shootDuration; } diff --git a/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java b/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java index c03f196367..72c0475aa2 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/LiquidTurret.java @@ -4,6 +4,7 @@ import arc.graphics.g2d.*; import arc.struct.*; import mindustry.annotations.Annotations.*; import mindustry.content.*; +import mindustry.core.*; import mindustry.entities.*; import mindustry.entities.bullet.*; import mindustry.gen.*; @@ -90,9 +91,7 @@ public class LiquidTurret extends Turret{ @Override public void updateTile(){ - if(unit != null){ - unit.ammo(unit.type().ammoCapacity * liquids.currentAmount() / liquidCapacity); - } + unit.ammo(unit.type().ammoCapacity * liquids.currentAmount() / liquidCapacity); super.updateTile(); } @@ -100,13 +99,14 @@ public class LiquidTurret extends Turret{ @Override protected void findTarget(){ if(extinguish && liquids.current().canExtinguish()){ + int tx = World.toTile(x), ty = World.toTile(y); Fire result = null; float mindst = 0f; int tr = (int)(range / tilesize); for(int x = -tr; x <= tr; x++){ for(int y = -tr; y <= tr; y++){ - Tile other = world.tile(x + tile.x, y + tile.y); - var fire = Fires.get(x + tile.x, y + tile.y); + Tile other = world.tile(x + tx, y + ty); + var fire = Fires.get(x + tx, y + ty); float dst = fire == null ? 0 : dst2(fire); //do not extinguish fires on other team blocks if(other != null && fire != null && Fires.has(other.x, other.y) && dst <= range * range && (result == null || dst < mindst) && (other.build == null || other.team() == team)){ diff --git a/core/src/mindustry/world/blocks/defense/turrets/PowerTurret.java b/core/src/mindustry/world/blocks/defense/turrets/PowerTurret.java index 7dc4eed3f6..4b19d33284 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/PowerTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/PowerTurret.java @@ -31,9 +31,7 @@ public class PowerTurret extends Turret{ @Override public void updateTile(){ - if(unit != null){ - unit.ammo(power.status * unit.type().ammoCapacity); - } + unit.ammo(power.status * unit.type().ammoCapacity); super.updateTile(); } diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java index 1e971d884c..29236505ab 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java @@ -149,15 +149,9 @@ public class Turret extends ReloadTurret{ public boolean logicShooting = false; public @Nullable Posc target; public Vec2 targetPos = new Vec2(); - public @Nullable BlockUnitc unit; + public BlockUnitc unit = (BlockUnitc)UnitTypes.block.create(team); public boolean wasShooting, charging; - @Override - public void created(){ - unit = (BlockUnitc)UnitTypes.block.create(team); - unit.tile(this); - } - @Override public boolean canControl(){ return playerControllable; @@ -165,7 +159,7 @@ public class Turret extends ReloadTurret{ @Override public void control(LAccess type, double p1, double p2, double p3, double p4){ - if(type == LAccess.shoot && (unit == null || !unit.isPlayer())){ + if(type == LAccess.shoot && !unit.isPlayer()){ targetPos.set(World.unconv((float)p1), World.unconv((float)p2)); logicControlTime = logicControlCooldown; logicShooting = !Mathf.zero(p3); @@ -203,15 +197,14 @@ public class Turret extends ReloadTurret{ } public boolean isShooting(){ - return (isControlled() ? (unit != null && unit.isShooting()) : logicControlled() ? logicShooting : target != null); + return (isControlled() ? unit.isShooting() : logicControlled() ? logicShooting : target != null); } @Override public Unit unit(){ - if(unit == null){ - unit = (BlockUnitc)UnitTypes.block.create(team); - unit.tile(this); - } + //make sure stats are correct + unit.tile(this); + unit.team(team); return (Unit)unit; } @@ -267,12 +260,9 @@ public class Turret extends ReloadTurret{ recoil = Mathf.lerpDelta(recoil, 0f, restitution); heat = Mathf.lerpDelta(heat, 0f, cooldown); - if(unit != null){ - unit.health(health); - unit.rotation(rotation); - unit.team(team); - unit.set(x, y); - } + unit.tile(this); + unit.rotation(rotation); + unit.team(team); if(logicControlTime > 0){ logicControlTime -= Time.delta; @@ -338,7 +328,7 @@ public class Turret extends ReloadTurret{ if(targetAir && !targetGround){ target = Units.bestEnemy(team, x, y, range, e -> !e.dead() && !e.isGrounded(), unitSort); }else{ - target = Units.bestTarget(team, x, y, range, e -> !e.dead() && (e.isGrounded() || targetAir) && (!e.isGrounded() || targetGround), b -> true, unitSort); + target = Units.bestTarget(team, x, y, range, e -> !e.dead() && (e.isGrounded() || targetAir) && (!e.isGrounded() || targetGround), b -> targetGround, unitSort); if(target == null && canHeal()){ target = Units.findAllyTile(team, x, y, range, b -> b.damaged() && b != this); @@ -405,7 +395,7 @@ public class Turret extends ReloadTurret{ for(int i = 0; i < chargeEffects; i++){ Time.run(Mathf.random(chargeMaxDelay), () -> { - if(!isValid()) return; + if(dead) return; tr.trns(rotation, shootLength); chargeEffect.at(x + tr.x, y + tr.y, rotation); }); @@ -414,7 +404,7 @@ public class Turret extends ReloadTurret{ charging = true; Time.run(chargeTime, () -> { - if(!isValid()) return; + if(dead) return; tr.trns(rotation, shootLength); recoil = recoilAmount; heat = 1f; @@ -428,7 +418,7 @@ public class Turret extends ReloadTurret{ for(int i = 0; i < shots; i++){ int ii = i; Time.run(burstSpacing * i, () -> { - if(!isValid() || !hasAmmo()) return; + if(dead || !hasAmmo()) return; recoil = recoilAmount; @@ -488,7 +478,7 @@ public class Turret extends ReloadTurret{ } protected void ejectEffects(){ - if(!isValid()) return; + if(dead) return; //alternate sides when using a double turret float scl = (shots == 2 && alternate && shotCounter % 2 == 1 ? -1f : 1f); diff --git a/core/src/mindustry/world/blocks/distribution/Conveyor.java b/core/src/mindustry/world/blocks/distribution/Conveyor.java index c45b6a7981..d91df61d7a 100644 --- a/core/src/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/mindustry/world/blocks/distribution/Conveyor.java @@ -22,7 +22,7 @@ import static mindustry.Vars.*; public class Conveyor extends Block implements Autotiler{ private static final float itemSpace = 0.4f; - private static final int capacity = 4; + private static final int capacity = 3; final Vec2 tr1 = new Vec2(); final Vec2 tr2 = new Vec2(); @@ -40,7 +40,7 @@ public class Conveyor extends Block implements Autotiler{ update = true; group = BlockGroup.transportation; hasItems = true; - itemCapacity = 4; + itemCapacity = capacity; conveyorPlacement = true; ambientSound = Sounds.conveyor; @@ -132,7 +132,7 @@ public class Conveyor extends Block implements Autotiler{ public float minitem = 1; public int blendbits, blending; - public int blendsclx, blendscly; + public int blendsclx = 1, blendscly = 1; public float clogHeat = 0f; @@ -163,12 +163,17 @@ public class Conveyor extends Block implements Autotiler{ tr2.trns(rotation * 90, -tilesize / 2f, xs[i] * tilesize / 2f); Draw.rect(item.fullIcon, - (tile.x * tilesize + tr1.x * ys[i] + tr2.x), - (tile.y * tilesize + tr1.y * ys[i] + tr2.y), + (x + tr1.x * ys[i] + tr2.x), + (y + tr1.y * ys[i] + tr2.y), itemSize, itemSize); } } + @Override + public void payloadDraw(){ + Draw.rect(block.fullIcon,x, y); + } + @Override public void drawCracks(){ Draw.z(Layer.block - 0.15f); @@ -323,7 +328,7 @@ public class Conveyor extends Block implements Autotiler{ @Override public void handleStack(Item item, int amount, Teamc source){ - amount = Math.min(amount, itemCapacity - len); + amount = Math.min(amount, capacity - len); for(int i = amount - 1; i >= 0; i--){ add(0); diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index 746ee0cfc7..9be6bb6428 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -184,6 +184,11 @@ public class ItemBridge extends Block{ public boolean wasMoved, moved; public float transportCounter; + @Override + public void pickedUp(){ + link = -1; + } + @Override public void playerPlaced(Object config){ super.playerPlaced(config); diff --git a/core/src/mindustry/world/blocks/distribution/MassDriver.java b/core/src/mindustry/world/blocks/distribution/MassDriver.java index c0bd7d73b2..f60d6b3c17 100644 --- a/core/src/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/mindustry/world/blocks/distribution/MassDriver.java @@ -165,7 +165,7 @@ public class MassDriver extends Block{ } //align to shooter rotation - rotation = Angles.moveToward(rotation, tile.angleTo(currentShooter()), rotateSpeed * efficiency()); + rotation = Angles.moveToward(rotation, angleTo(currentShooter()), rotateSpeed * efficiency()); }else if(state == DriverState.shooting){ //if there's nothing to shoot at OR someone wants to shoot at this thing, bail if(!hasLink || (!waitingShooters.isEmpty() && (itemCapacity - items.total() >= minDistribute))){ @@ -173,7 +173,7 @@ public class MassDriver extends Block{ return; } - float targetRotation = tile.angleTo(link); + float targetRotation = angleTo(link); if( items.total() >= minDistribute && //must shoot minimum amount of items diff --git a/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java b/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java index 2681376e35..119d00d671 100644 --- a/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java +++ b/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java @@ -114,7 +114,7 @@ public class PayloadConveyor extends Block{ int ntrns = 1 + size/2; Tile next = tile.nearby(Geometry.d4(rotation).x * ntrns, Geometry.d4(rotation).y * ntrns); - blocked = (next != null && next.solid() && !(next.block().outputsPayload || next.block().acceptsPayload)) || (this.next != null && this.next.block.rotate && (this.next.rotation + 2) % 4 == rotation); + blocked = (next != null && next.solid() && !(next.block().outputsPayload || next.block().acceptsPayload)) || (this.next != null && this.next.payloadCheck(rotation)); } @Override @@ -126,6 +126,10 @@ public class PayloadConveyor extends Block{ public void updateTile(){ if(!enabled) return; + if(item != null){ + item.update(); + } + lastInterp = curInterp; curInterp = fract(); //rollover skip @@ -231,6 +235,11 @@ public class PayloadConveyor extends Block{ } } + @Override + public void payloadDraw(){ + Draw.rect(block.fullIcon,x, y); + } + public float time(){ return Time.time; } diff --git a/core/src/mindustry/world/blocks/liquid/Conduit.java b/core/src/mindustry/world/blocks/liquid/Conduit.java index 11ba66255b..8e6249e828 100644 --- a/core/src/mindustry/world/blocks/liquid/Conduit.java +++ b/core/src/mindustry/world/blocks/liquid/Conduit.java @@ -97,7 +97,7 @@ public class Conduit extends LiquidBlock implements Autotiler{ public class ConduitBuild extends LiquidBuild implements ChainedBuilding{ public float smoothLiquid; - public int blendbits, xscl, yscl, blending; + public int blendbits, xscl = 1, yscl = 1, blending; public boolean capped; @Override diff --git a/core/src/mindustry/world/blocks/logic/LogicBlock.java b/core/src/mindustry/world/blocks/logic/LogicBlock.java index e8cf14ef16..411e0067b5 100644 --- a/core/src/mindustry/world/blocks/logic/LogicBlock.java +++ b/core/src/mindustry/world/blocks/logic/LogicBlock.java @@ -7,7 +7,6 @@ import arc.struct.Bits; import arc.struct.*; import arc.util.*; import arc.util.io.*; -import mindustry.*; import mindustry.ai.types.*; import mindustry.core.*; import mindustry.gen.*; @@ -493,7 +492,7 @@ public class LogicBlock extends Block{ @Override public void buildConfiguration(Table table){ table.button(Icon.pencil, Styles.clearTransi, () -> { - Vars.ui.logic.show(code, code -> configure(compress(code, relativeConnections()))); + ui.logic.show(code, executor, code -> configure(compress(code, relativeConnections()))); }).size(40); } diff --git a/core/src/mindustry/world/blocks/logic/MessageBlock.java b/core/src/mindustry/world/blocks/logic/MessageBlock.java index 3a982c37cb..1c373056dc 100644 --- a/core/src/mindustry/world/blocks/logic/MessageBlock.java +++ b/core/src/mindustry/world/blocks/logic/MessageBlock.java @@ -119,7 +119,7 @@ public class MessageBlock extends Block{ dialog.hide(); }).size(130f, 60f); dialog.update(() -> { - if(tile.block() != MessageBlock.this){ + if(tile.build != this){ dialog.hide(); } }); diff --git a/core/src/mindustry/world/blocks/payloads/BlockProducer.java b/core/src/mindustry/world/blocks/payloads/BlockProducer.java index a3186a0dc3..43da658451 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockProducer.java +++ b/core/src/mindustry/world/blocks/payloads/BlockProducer.java @@ -78,6 +78,7 @@ public abstract class BlockProducer extends PayloadBlock{ @Override public void updateTile(){ + super.updateTile(); var recipe = recipe(); boolean produce = recipe != null && consValid() && payload == null; diff --git a/core/src/mindustry/world/blocks/payloads/BuildPayload.java b/core/src/mindustry/world/blocks/payloads/BuildPayload.java index ad6a6a0fc9..21753a7d35 100644 --- a/core/src/mindustry/world/blocks/payloads/BuildPayload.java +++ b/core/src/mindustry/world/blocks/payloads/BuildPayload.java @@ -1,6 +1,7 @@ package mindustry.world.blocks.payloads; import arc.graphics.g2d.*; +import arc.math.*; import arc.util.io.*; import mindustry.game.*; import mindustry.gen.*; @@ -15,6 +16,7 @@ public class BuildPayload implements Payload{ public BuildPayload(Block block, Team team){ this.build = block.newBuilding().create(block, team); + this.build.tile = emptyTile; } public BuildPayload(Building build){ @@ -34,6 +36,12 @@ public class BuildPayload implements Payload{ build.dropped(); } + @Override + public void update(){ + if(build.tile == null) build.tile = emptyTile; + build.update(); + } + @Override public ItemStack[] requirements(){ return build.block.requirements; @@ -80,7 +88,10 @@ public class BuildPayload implements Payload{ @Override public void draw(){ drawShadow(1f); - Draw.rect(build.block.fullIcon, build.x, build.y); + float prevZ = Draw.z(); + Draw.zTransform(z -> 0.0011f + Mathf.clamp(z, prevZ - 0.001f, prevZ + 0.9f)); + build.payloadDraw(); + Draw.zTransform(); } @Override diff --git a/core/src/mindustry/world/blocks/payloads/Constructor.java b/core/src/mindustry/world/blocks/payloads/Constructor.java index b6be3779dc..108017cbb4 100644 --- a/core/src/mindustry/world/blocks/payloads/Constructor.java +++ b/core/src/mindustry/world/blocks/payloads/Constructor.java @@ -8,6 +8,7 @@ import arc.util.io.*; import mindustry.*; import mindustry.world.*; import mindustry.world.blocks.*; +import mindustry.world.blocks.storage.*; import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -23,6 +24,7 @@ public class Constructor extends BlockProducer{ size = 3; configurable = true; + configClear((ConstructorBuild tile) -> tile.recipe = null); config(Block.class, (ConstructorBuild tile, Block block) -> { if(tile.recipe != block) tile.progress = 0f; if(canProduce(block)){ @@ -40,7 +42,7 @@ public class Constructor extends BlockProducer{ } public boolean canProduce(Block b){ - return b.isVisible() && b.size >= minBlockSize && b.size <= maxBlockSize; + return b.isVisible() && b.size >= minBlockSize && b.size <= maxBlockSize && !(b instanceof CoreBlock) && !state.rules.bannedBlocks.contains(b); } public class ConstructorBuild extends BlockProducerBuild{ diff --git a/core/src/mindustry/world/blocks/payloads/Payload.java b/core/src/mindustry/world/blocks/payloads/Payload.java index 4be19f66bf..194a91a5a3 100644 --- a/core/src/mindustry/world/blocks/payloads/Payload.java +++ b/core/src/mindustry/world/blocks/payloads/Payload.java @@ -36,6 +36,9 @@ public interface Payload extends Position{ /** @return the time taken to build this payload. */ float buildTime(); + /** update this payload if it is a block */ + default void update(){} + /** @return whether this payload was dumped. */ default boolean dump(){ return false; @@ -94,6 +97,7 @@ public interface Payload extends Position{ BuildPayload payload = new BuildPayload(block, Team.derelict); byte version = read.b(); payload.build.readAll(read, version); + payload.build.tile = emptyTile; return (T)payload; }else if(type == payloadUnit){ byte id = read.b(); diff --git a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java index 86247f85aa..8fee45f2e6 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java @@ -135,6 +135,13 @@ public class PayloadBlock extends Block{ if(payload != null && !carried) payload.dump(); } + @Override + public void updateTile(){ + if(payload != null){ + payload.update(); + } + } + public boolean blends(int direction){ return PayloadBlock.blends(this, direction); } diff --git a/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java b/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java index 328549f0a4..096461181b 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java @@ -85,6 +85,11 @@ public class PayloadDeconstructor extends PayloadBlock{ Draw.rect(topRegion, x, y); } + @Override + public boolean acceptUnitPayload(Unit unit){ + return payload == null && deconstructing == null && !unit.spawnedByCore && unit.type.getTotalRequirements().length > 0 && unit.hitSize / tilesize <= maxPayloadSize; + } + @Override public void handlePayload(Building source, Payload payload){ super.handlePayload(source, payload); @@ -93,11 +98,12 @@ public class PayloadDeconstructor extends PayloadBlock{ @Override public boolean acceptPayload(Building source, Payload payload){ - return deconstructing == null && super.acceptPayload(source, payload) && payload.requirements().length > 0 && payload.fits(maxPayloadSize); + return deconstructing == null && this.payload == null && super.acceptPayload(source, payload) && payload.requirements().length > 0 && payload.fits(maxPayloadSize); } @Override public void updateTile(){ + super.updateTile(); if(items.total() > 0){ for(int i = 0; i < dumpRate; i++){ dumpAccumulate(); @@ -153,10 +159,26 @@ public class PayloadDeconstructor extends PayloadBlock{ //finish deconstruction, prepare for next payload. if(progress >= 1f){ - Fx.breakBlock.at(x, y, deconstructing.size() / tilesize); + canProgress = true; + //check for rounding errors + for(int i = 0; i < reqs.length; i++){ + if(Mathf.equal(accum[i], 1f, 0.0001f)){ + if(items.total() < itemCapacity){ + items.add(reqs[i].item, 1); + accum[i] = 0f; + }else{ + canProgress = false; + break; + } + } + } - deconstructing = null; - accum = null; + if(canProgress){ + Fx.breakBlock.at(x, y, deconstructing.size() / tilesize); + + deconstructing = null; + accum = null; + } } }else if(moveInPayload(false) && payload != null){ accum = new float[payload.requirements().length]; diff --git a/core/src/mindustry/world/blocks/payloads/PayloadLoader.java b/core/src/mindustry/world/blocks/payloads/PayloadLoader.java index 04c2d7c60b..67b826d55a 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadLoader.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadLoader.java @@ -3,6 +3,7 @@ package mindustry.world.blocks.payloads; import arc.*; import arc.graphics.g2d.*; import arc.util.*; +import arc.util.io.*; import mindustry.entities.units.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -58,15 +59,23 @@ public class PayloadLoader extends PayloadBlock{ } public class PayloadLoaderBuild extends PayloadBlockBuild{ + public boolean exporting = false; @Override public boolean acceptPayload(Building source, Payload payload){ return super.acceptPayload(source, payload) && + payload.fits(maxBlockSize) && payload instanceof BuildPayload build && ((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize) || build.build.block().hasLiquids && build.block().liquidCapacity >= 10f); } + @Override + public void handlePayload(Building source, Payload payload){ + super.handlePayload(source, payload); + exporting = false; + } + @Override public boolean acceptItem(Building source, Item item){ return items.total() < itemCapacity; @@ -102,6 +111,7 @@ public class PayloadLoader extends PayloadBlock{ @Override public void updateTile(){ + super.updateTile(); if(shouldExport()){ moveOutPayload(); }else if(moveInPayload()){ @@ -119,6 +129,9 @@ public class PayloadLoader extends PayloadBlock{ payload.build.handleItem(payload.build, item); items.remove(item, 1); break; + }else if(payload.block().separateItemCapacity || payload.block().consumes.consumesItem(item)){ + exporting = true; + break; } } } @@ -146,8 +159,28 @@ public class PayloadLoader extends PayloadBlock{ public boolean shouldExport(){ return payload != null && ( + exporting || (payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) || - (payload.block().hasItems && payload.build.items.total() >= payload.block().itemCapacity)); + (payload.block().hasItems && payload.block().separateItemCapacity && content.items().contains(i -> payload.build.items.get(i) >= payload.block().itemCapacity))); + } + + @Override + public byte version(){ + return 1; + } + + @Override + public void write(Writes write){ + super.write(write); + write.bool(exporting); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); + if(revision >= 1){ + exporting = read.bool(); + } } } } diff --git a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java index 7087c5f008..922a93899b 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java @@ -143,6 +143,7 @@ public class PayloadMassDriver extends PayloadBlock{ @Override public void updateTile(){ + super.updateTile(); Building link = world.build(this.link); boolean hasLink = linkValid(); @@ -233,7 +234,7 @@ public class PayloadMassDriver extends PayloadBlock{ } //align to shooter rotation - turretRotation = Angles.moveToward(turretRotation, tile.angleTo(currentShooter()), rotateSpeed * efficiency()); + turretRotation = Angles.moveToward(turretRotation, angleTo(currentShooter()), rotateSpeed * efficiency()); }else if(state == shooting){ //if there's nothing to shoot at OR someone wants to shoot at this thing, bail if(!hasLink || (!waitingShooters.isEmpty() && payload == null)){ @@ -241,7 +242,7 @@ public class PayloadMassDriver extends PayloadBlock{ return; } - float targetRotation = tile.angleTo(link); + float targetRotation = angleTo(link); boolean movedOut = false; payRotation = Angles.moveToward(payRotation, turretRotation, payloadRotateSpeed * delta()); diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index 62600833b9..d1f37a436b 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -103,6 +103,7 @@ public class PayloadSource extends PayloadBlock{ @Override public void updateTile(){ + super.updateTile(); if(payload == null){ scl = 0f; if(unit != null){ diff --git a/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java b/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java index 7d63380528..2746516abe 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java @@ -36,6 +36,7 @@ public class PayloadUnloader extends PayloadLoader{ @Override public void updateTile(){ + super.updateTile(); if(shouldExport()){ //one-use, disposable block if(payload.block().instantDeconstruct){ diff --git a/core/src/mindustry/world/blocks/payloads/PayloadVoid.java b/core/src/mindustry/world/blocks/payloads/PayloadVoid.java index 9ef2cb5800..cc429794fe 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadVoid.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadVoid.java @@ -55,6 +55,7 @@ public class PayloadVoid extends PayloadBlock{ @Override public void updateTile(){ + super.updateTile(); if(moveInPayload(false) && cons.valid()){ payload = null; incinerateEffect.at(this); diff --git a/core/src/mindustry/world/blocks/power/ImpactReactor.java b/core/src/mindustry/world/blocks/power/ImpactReactor.java index 3679b2be80..45e8f394f4 100644 --- a/core/src/mindustry/world/blocks/power/ImpactReactor.java +++ b/core/src/mindustry/world/blocks/power/ImpactReactor.java @@ -141,7 +141,7 @@ public class ImpactReactor extends PowerGenerator{ if(warmup < 0.3f || !state.rules.reactorExplosions) return; - Sounds.explosionbig.at(tile); + Sounds.explosionbig.at(this); Damage.damage(x, y, explosionRadius * tilesize, explosionDamage * 4); diff --git a/core/src/mindustry/world/blocks/power/NuclearReactor.java b/core/src/mindustry/world/blocks/power/NuclearReactor.java index a26a99d5cd..ba8394b90a 100644 --- a/core/src/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/mindustry/world/blocks/power/NuclearReactor.java @@ -76,6 +76,7 @@ public class NuclearReactor extends PowerGenerator{ public class NuclearReactorBuild extends GeneratorBuild{ public float heat; + public float flash; @Override public void updateTile(){ @@ -130,7 +131,7 @@ public class NuclearReactor extends PowerGenerator{ public void onDestroyed(){ super.onDestroyed(); - Sounds.explosionbig.at(tile); + Sounds.explosionbig.at(this); int fuel = items.get(consumes.get(ConsumeType.item).items[0].item); @@ -160,10 +161,9 @@ public class NuclearReactor extends PowerGenerator{ Draw.rect(topRegion, x, y); if(heat > flashThreshold){ - float flash = 1f + ((heat - flashThreshold) / (1f - flashThreshold)) * 5.4f; - flash += flash * Time.delta; + flash += (1f + ((heat - flashThreshold) / (1f - flashThreshold)) * 5.4f) * Time.delta; Draw.color(Color.red, Color.yellow, Mathf.absin(flash, 9f, 1f)); - Draw.alpha(0.6f); + Draw.alpha(0.3f); Draw.rect(lightsRegion, x, y); } diff --git a/core/src/mindustry/world/blocks/power/PowerDiode.java b/core/src/mindustry/world/blocks/power/PowerDiode.java index f31cf71cf6..20db770b82 100644 --- a/core/src/mindustry/world/blocks/power/PowerDiode.java +++ b/core/src/mindustry/world/blocks/power/PowerDiode.java @@ -56,7 +56,7 @@ public class PowerDiode extends Block{ public void updateTile(){ super.updateTile(); - if(front() == null || back() == null || !back().block.hasPower || !front().block.hasPower || back().team != front().team) return; + if(tile == null || front() == null || back() == null || !back().block.hasPower || !front().block.hasPower || back().team != front().team) return; PowerGraph backGraph = back().power.graph; PowerGraph frontGraph = front().power.graph; diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java index 8ee013f6fe..4c59a84174 100644 --- a/core/src/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/mindustry/world/blocks/power/PowerNode.java @@ -444,7 +444,7 @@ public class PowerNode extends PowerBlock{ public void draw(){ super.draw(); - if(Mathf.zero(Renderer.laserOpacity)) return; + if(Mathf.zero(Renderer.laserOpacity) || isPayload()) return; Draw.z(Layer.power); setupColor(power.graph.getSatisfaction()); diff --git a/core/src/mindustry/world/blocks/production/AttributeCrafter.java b/core/src/mindustry/world/blocks/production/AttributeCrafter.java index 381e7af5e0..e11ba156ed 100644 --- a/core/src/mindustry/world/blocks/production/AttributeCrafter.java +++ b/core/src/mindustry/world/blocks/production/AttributeCrafter.java @@ -52,6 +52,11 @@ public class AttributeCrafter extends GenericCrafter{ return baseEfficiency + Math.min(maxBoost, boostScale * attrsum) + attribute.env(); } + @Override + public void pickedUp(){ + attrsum = 0f; + } + @Override public void onProximityUpdate(){ super.onProximityUpdate(); diff --git a/core/src/mindustry/world/blocks/production/Drill.java b/core/src/mindustry/world/blocks/production/Drill.java index fa3a274301..d31a130f96 100644 --- a/core/src/mindustry/world/blocks/production/Drill.java +++ b/core/src/mindustry/world/blocks/production/Drill.java @@ -243,6 +243,11 @@ public class Drill extends Block{ } } + @Override + public void pickedUp(){ + dominantItem = null; + } + @Override public void onProximityUpdate(){ super.onProximityUpdate(); diff --git a/core/src/mindustry/world/blocks/production/Pump.java b/core/src/mindustry/world/blocks/production/Pump.java index 9a9aca65c3..f18b0c7640 100644 --- a/core/src/mindustry/world/blocks/production/Pump.java +++ b/core/src/mindustry/world/blocks/production/Pump.java @@ -91,6 +91,11 @@ public class Pump extends LiquidBlock{ Drawf.liquid(liquidRegion, x, y, liquids.currentAmount() / liquidCapacity, liquids.current().color); } + @Override + public void pickedUp(){ + amount = 0f; + } + @Override public void onProximityUpdate(){ super.onProximityUpdate(); diff --git a/core/src/mindustry/world/blocks/production/SolidPump.java b/core/src/mindustry/world/blocks/production/SolidPump.java index 912af46b18..7bd7cb9bed 100644 --- a/core/src/mindustry/world/blocks/production/SolidPump.java +++ b/core/src/mindustry/world/blocks/production/SolidPump.java @@ -95,6 +95,11 @@ public class SolidPump extends Pump{ @Override public void drawCracks(){} + @Override + public void pickedUp(){ + boost = validTiles = 0f; + } + @Override public void draw(){ Draw.rect(region, x, y); diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java index 6135288c3c..01b50b10bf 100644 --- a/core/src/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java @@ -20,6 +20,7 @@ public class StorageBlock extends Block{ solid = true; update = false; destructible = true; + separateItemCapacity = true; group = BlockGroup.transportation; flags = EnumSet.of(BlockFlag.storage); allowResupply = true; diff --git a/core/src/mindustry/world/blocks/units/CommandCenter.java b/core/src/mindustry/world/blocks/units/CommandCenter.java index 3d8f9c024f..0629727acf 100644 --- a/core/src/mindustry/world/blocks/units/CommandCenter.java +++ b/core/src/mindustry/world/blocks/units/CommandCenter.java @@ -97,9 +97,9 @@ public class CommandCenter extends Block{ float size = 6f; Draw.color(bottomColor); - Draw.rect(commandRegions[team.data().command.ordinal()].getRegion(), tile.drawx(), tile.drawy() - 1, size, size); + Draw.rect(commandRegions[team.data().command.ordinal()].getRegion(), x, y - 1, size, size); Draw.color(topColor == null ? team.color : topColor); - Draw.rect(commandRegions[team.data().command.ordinal()].getRegion(), tile.drawx(), tile.drawy(), size, size); + Draw.rect(commandRegions[team.data().command.ordinal()].getRegion(), x, y, size, size); Draw.color(); } diff --git a/core/src/mindustry/world/blocks/units/Reconstructor.java b/core/src/mindustry/world/blocks/units/Reconstructor.java index 0d84db2fb5..b73b51547c 100644 --- a/core/src/mindustry/world/blocks/units/Reconstructor.java +++ b/core/src/mindustry/world/blocks/units/Reconstructor.java @@ -185,6 +185,12 @@ public class Reconstructor extends UnitBlock{ Draw.rect(topRegion, x, y); } + @Override + public Object senseObject(LAccess sensor){ + if(sensor == LAccess.config) return unit(); + return super.senseObject(sensor); + } + @Override public void updateTile(){ boolean valid = false; diff --git a/core/src/mindustry/world/blocks/units/RepairPoint.java b/core/src/mindustry/world/blocks/units/RepairPoint.java index 3ca61ec0d7..3c723c49e3 100644 --- a/core/src/mindustry/world/blocks/units/RepairPoint.java +++ b/core/src/mindustry/world/blocks/units/RepairPoint.java @@ -176,7 +176,7 @@ public class RepairPoint extends Block{ multiplier = liq.valid(this) ? 1f + liquids.current().heatCapacity * coolantMultiplier : 1f; } - if(target != null && (target.dead() || target.dst(tile) - target.hitSize/2f > repairRadius || target.health() >= target.maxHealth())){ + if(target != null && (target.dead() || target.dst(this) - target.hitSize/2f > repairRadius || target.health() >= target.maxHealth())){ target = null; } diff --git a/core/src/mindustry/world/consumers/ConsumePower.java b/core/src/mindustry/world/consumers/ConsumePower.java index 991ad968e7..82addb8a3a 100644 --- a/core/src/mindustry/world/consumers/ConsumePower.java +++ b/core/src/mindustry/world/consumers/ConsumePower.java @@ -68,7 +68,7 @@ public class ConsumePower extends Consume{ * @return The amount of power which is requested per tick. */ public float requestedPower(Building entity){ - if(entity.tile().build == null) return 0f; + if(entity.tile == null || entity.tile.build == null) return 0f; if(buffered){ return (1f-entity.power.status)*capacity; }else{ diff --git a/core/src/mindustry/world/consumers/Consumers.java b/core/src/mindustry/world/consumers/Consumers.java index 0b64e3d78f..9fdba8d2ec 100644 --- a/core/src/mindustry/world/consumers/Consumers.java +++ b/core/src/mindustry/world/consumers/Consumers.java @@ -16,6 +16,14 @@ public class Consumers{ public final Bits itemFilters = new Bits(Vars.content.items().size); public final Bits liquidfilters = new Bits(Vars.content.liquids().size); + public boolean consumesItem(Item item){ + return itemFilters.get(item.id); + } + + public boolean consumesLiquid(Liquid liq){ + return liquidfilters.get(liq.id); + } + public boolean any(){ return results != null && results.length > 0; } diff --git a/core/src/mindustry/world/meta/BlockStatus.java b/core/src/mindustry/world/meta/BlockStatus.java index fa939ec8c7..d21887244e 100644 --- a/core/src/mindustry/world/meta/BlockStatus.java +++ b/core/src/mindustry/world/meta/BlockStatus.java @@ -6,7 +6,8 @@ import mindustry.graphics.*; public enum BlockStatus{ active(Color.valueOf("5ce677")), noOutput(Color.orange), - noInput(Pal.remove); + noInput(Pal.remove), + logicDisable(Color.valueOf("8a73c6")); public final Color color; diff --git a/core/src/mindustry/world/modules/ConsumeModule.java b/core/src/mindustry/world/modules/ConsumeModule.java index 4714903c5d..4973f4151f 100644 --- a/core/src/mindustry/world/modules/ConsumeModule.java +++ b/core/src/mindustry/world/modules/ConsumeModule.java @@ -14,6 +14,10 @@ public class ConsumeModule extends BlockModule{ } public BlockStatus status(){ + if(entity.enabledControlTime > 0 && !entity.enabled){ + return BlockStatus.logicDisable; + } + if(!entity.shouldConsume()){ return BlockStatus.noOutput; } diff --git a/gradle.properties b/gradle.properties index a54ba48d55..484eca99f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,4 +24,4 @@ android.useAndroidX=true #used for slow jitpack builds; TODO see if this actually works org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.connectionTimeout=100000 -archash=6c228e534e3950e6254d6e7af4c6db67f834bc1d +archash=a40808f513dd04b3f3877595456d7e112b5ae4bd diff --git a/ios/data/Default-568h@2x~iphone.png b/ios/data/Default-568h@2x~iphone.png deleted file mode 100644 index 9a0e377f65..0000000000 Binary files a/ios/data/Default-568h@2x~iphone.png and /dev/null differ diff --git a/ios/data/Default-667h.png b/ios/data/Default-667h.png deleted file mode 100644 index b5a4b57681..0000000000 Binary files a/ios/data/Default-667h.png and /dev/null differ diff --git a/ios/data/Default-736h.png b/ios/data/Default-736h.png deleted file mode 100644 index 8d05a25f44..0000000000 Binary files a/ios/data/Default-736h.png and /dev/null differ diff --git a/ios/data/Default-Landscape-736h.png b/ios/data/Default-Landscape-736h.png deleted file mode 100644 index 70badabb86..0000000000 Binary files a/ios/data/Default-Landscape-736h.png and /dev/null differ diff --git a/ios/data/Default-Landscape@2x~ipad.png b/ios/data/Default-Landscape@2x~ipad.png deleted file mode 100644 index da2884cfd1..0000000000 Binary files a/ios/data/Default-Landscape@2x~ipad.png and /dev/null differ diff --git a/ios/data/Default-Landscape~ipad.png b/ios/data/Default-Landscape~ipad.png deleted file mode 100644 index 3b101edc7e..0000000000 Binary files a/ios/data/Default-Landscape~ipad.png and /dev/null differ diff --git a/ios/data/Default-Portrait@2x~ipad.png b/ios/data/Default-Portrait@2x~ipad.png deleted file mode 100644 index 0989e62081..0000000000 Binary files a/ios/data/Default-Portrait@2x~ipad.png and /dev/null differ diff --git a/ios/data/Default-Portrait~ipad.png b/ios/data/Default-Portrait~ipad.png deleted file mode 100644 index 9f980c961a..0000000000 Binary files a/ios/data/Default-Portrait~ipad.png and /dev/null differ diff --git a/ios/data/Default@2x~iphone.png b/ios/data/Default@2x~iphone.png deleted file mode 100644 index 710599b407..0000000000 Binary files a/ios/data/Default@2x~iphone.png and /dev/null differ diff --git a/ios/data/Default~iphone.png b/ios/data/Default~iphone.png deleted file mode 100644 index 527d691cc0..0000000000 Binary files a/ios/data/Default~iphone.png and /dev/null differ diff --git a/servers_v6.json b/servers_v6.json index 45bd95fe2b..0de119cb8f 100644 --- a/servers_v6.json +++ b/servers_v6.json @@ -117,6 +117,10 @@ }, { "name": "MindustryBR", - "address": ["mindustryptbr.ddns.net", "mindustryptbr.myddns.me"] + "address": ["mindustryptbr.ddns.net", "mindustryptbr.myddns.me", "mindustry.me:4447"] + }, + { + "name": "Conservatory", + "address": ["143.198.71.232"] } ] diff --git a/servers_v7.json b/servers_v7.json index 2e48a3cfef..4ee885dabd 100644 --- a/servers_v7.json +++ b/servers_v7.json @@ -58,5 +58,13 @@ { "name": "Phoenix Network", "address": ["172.104.253.198"] + }, + { + "name": "Pandorum", + "address": ["pandorum.su:5018", "pandorum.su:5019", "pandorum.su:5020"] + }, + { + "name": "MindustryBR", + "address": ["mindustry.me:4451", "n2.mindustry.me:4446"] } ] diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 01dce8947e..c486e7e101 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -24,6 +24,7 @@ import mindustry.net.*; import mindustry.net.Packets.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.payloads.*; import mindustry.world.blocks.storage.*; import org.junit.jupiter.api.*; import org.junit.jupiter.params.*; @@ -791,6 +792,57 @@ public class ApplicationTests{ } } + void checkPayloads(){ + for(int x = 0; x < world.tiles.width; x++){ + for(int y = 0; y < world.tiles.height; y++){ + Tile tile = world.rawTile(x, y); + if(tile.build != null && tile.isCenter() && !(tile.block() instanceof CoreBlock)){ + try{ + tile.build.update(); + }catch(Throwable t){ + fail("Failed to update block in payload: '" + ((BuildPayload)tile.build.getPayload()).block() + "'", t); + } + assertEquals(tile.block(), tile.build.block); + assertEquals(tile.block().health, tile.build.health()); + } + } + } + } + + @Test + void allPayloadBlockTest(){ + int ts = 20; + Tiles tiles = world.resize(ts * 3, ts * 3); + + world.beginMapLoad(); + for(int x = 0; x < tiles.width; x++){ + for(int y = 0; y < tiles.height; y++){ + tiles.set(x, y, new Tile(x, y, Blocks.stone, Blocks.air, Blocks.air)); + } + } + + tiles.getn(tiles.width - 2, tiles.height - 2).setBlock(Blocks.coreShard, Team.sharded); + + Seq blocks = content.blocks().select(b -> b.canBeBuilt()); + for(int i = 0; i < blocks.size; i++){ + int x = (i % ts) * 3 + 1; + int y = (i / ts) * 3 + 1; + Tile tile = tiles.get(x, y); + tile.setBlock(Blocks.payloadConveyor, Team.sharded); + Building build = tile.build; + build.handlePayload(build, new BuildPayload(blocks.get(i), Team.sharded)); + } + world.endMapLoad(); + + checkPayloads(); + + SaveIO.write(saveDirectory.child("payloads.msav")); + logic.reset(); + SaveIO.load(saveDirectory.child("payloads.msav")); + + checkPayloads(); + } + @TestFactory DynamicTest[] testSectorValidity(){ Seq out = new Seq<>(); diff --git a/tools/src/mindustry/tools/Generators.java b/tools/src/mindustry/tools/Generators.java index 1349312ddf..838c713a6d 100644 --- a/tools/src/mindustry/tools/Generators.java +++ b/tools/src/mindustry/tools/Generators.java @@ -477,8 +477,8 @@ public class Generators{ Pixmap baseCell = get(type.cellRegion); Pixmap cell = baseCell.copy(); - //replace with 0xffd37fff : 0xdca463ff for sharded colors? - cell.replace(in -> in == 0xffffffff ? 0xffa664ff : in == 0xdcc6c6ff ? 0xd06b53ff : 0); + //replace with 0xffd37fff : 0xdca463ff for sharded colors? + cell.replace(in -> in == 0xffffffff ? 0xffa664ff : in == 0xdcc6c6ff || in == 0xdcc5c5ff ? 0xd06b53ff : 0); image.draw(cell, image.width / 2 - cell.width / 2, image.height / 2 - cell.height / 2, true); }