1
0
mirror of https://github.com/Anuken/Mindustry.git synced 2024-09-11 08:15:35 +03:00

Merge branch 'master' of https://github.com/Anuken/Mindustry into 7.0-features

 Conflicts:
	core/src/mindustry/content/Planets.java
	tools/src/mindustry/tools/Generators.java
This commit is contained in:
Anuken 2021-10-20 10:45:51 -04:00
commit d3343c0ae9
78 changed files with 585 additions and 156 deletions

View File

@ -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<String> names = new HashSet<>();
Seq<Fi> 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());

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -415,6 +415,7 @@ wavemode.health = health
editor.default = [lightgray]<Default>
details = Details...
edit = Edit...
variables = Vars
editor.name = Name:
editor.spawn = Spawn Unit
editor.removeunit = Remove Unit

View File

@ -415,6 +415,7 @@ wavemode.health = vie
editor.default = [lightgray]<par défaut>
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.

View File

@ -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 = 구조물 건설

View File

@ -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 = Усовершенствованный силовой узел с большей дальностью.

View File

@ -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 = สร้างสิ่งก่อสร้าง

View File

@ -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]<Varsayılan>
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.

View File

@ -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 = Побудувати будівлю.

View File

@ -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();
}

View File

@ -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(

View File

@ -88,7 +88,9 @@ public class TechTree implements ContentList{
node(conduit, () -> {
node(liquidJunction, () -> {
node(liquidRouter, () -> {
node(liquidTank);
node(liquidContainer, () -> {
node(liquidTank);
});
node(bridgeConduit);

View File

@ -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;

View File

@ -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);
}

View File

@ -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<Payload> grabber){
Fx.spawn.at(player);
public void handleUnitPayload(Unit unit, Cons<Payload> 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);
}

View File

@ -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

View File

@ -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));

View File

@ -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);
}

View File

@ -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;

View File

@ -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{

View File

@ -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<String> 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<String> modified){
public void show(String code, LExecutor executor, Cons<String> modified){
this.executor = executor;
canvas.statements.clearChildren();
canvas.rebuild();
try{

View File

@ -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();
}
});

View File

@ -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;

View File

@ -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){

View File

@ -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;

View File

@ -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;
}

View File

@ -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)){

View File

@ -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();
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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();
}
});

View File

@ -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;

View File

@ -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

View File

@ -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{

View File

@ -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();

View File

@ -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);
}

View File

@ -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];

View File

@ -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<BuildPayload>{
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();
}
}
}
}

View File

@ -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());

View File

@ -103,6 +103,7 @@ public class PayloadSource extends PayloadBlock{
@Override
public void updateTile(){
super.updateTile();
if(payload == null){
scl = 0f;
if(unit != null){

View File

@ -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){

View File

@ -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);

View File

@ -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);

View File

@ -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.<ConsumeItems>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);
}

View File

@ -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;

View File

@ -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());

View File

@ -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();

View File

@ -243,6 +243,11 @@ public class Drill extends Block{
}
}
@Override
public void pickedUp(){
dominantItem = null;
}
@Override
public void onProximityUpdate(){
super.onProximityUpdate();

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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{

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 706 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 725 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

View File

@ -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"]
}
]

View File

@ -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"]
}
]

View File

@ -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<Block> 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<DynamicTest> out = new Seq<>();

View File

@ -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);
}