This commit is contained in:
Anuken
2024-08-24 10:18:47 -04:00
75 changed files with 270 additions and 130 deletions

View File

@@ -502,6 +502,7 @@ wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<Default> editor.default = [lightgray]<Default>
details = Details... details = Details...
edit = Edit edit = Edit

View File

@@ -489,6 +489,7 @@ waves.units.show = Паказаць Усё
wavemode.counts = колькацсь адзінак wavemode.counts = колькацсь адзінак
wavemode.totals = усяго здароўя wavemode.totals = усяго здароўя
wavemode.health = здароўе wavemode.health = здароўе
all = All
editor.default = [lightgray]<Па змаўчанні> editor.default = [lightgray]<Па змаўчанні>
details = Падрабязнасці... details = Падрабязнасці...

View File

@@ -495,6 +495,7 @@ waves.units.show = Show All
wavemode.counts = бройки wavemode.counts = бройки
wavemode.totals = общи бройки wavemode.totals = общи бройки
wavemode.health = точки живот wavemode.health = точки живот
all = All
editor.default = [lightgray]<Стандартно> editor.default = [lightgray]<Стандартно>
details = Детайли... details = Детайли...

View File

@@ -495,6 +495,7 @@ waves.units.show = Mostra-les totes
wavemode.counts = comptades wavemode.counts = comptades
wavemode.totals = totals wavemode.totals = totals
wavemode.health = salut wavemode.health = salut
all = All
editor.default = [lightgray]<Per defecte> editor.default = [lightgray]<Per defecte>
details = Detalls details = Detalls

View File

@@ -496,6 +496,7 @@ waves.units.show = Zobrazit vše
wavemode.counts = počty wavemode.counts = počty
wavemode.totals = součty wavemode.totals = součty
wavemode.health = zdraví wavemode.health = zdraví
all = All
editor.default = [lightgray]<Výchozí>[] editor.default = [lightgray]<Výchozí>[]
details = Podrobnosti... details = Podrobnosti...

View File

@@ -490,6 +490,7 @@ waves.units.show = Show All
wavemode.counts = tal wavemode.counts = tal
wavemode.totals = i alt wavemode.totals = i alt
wavemode.health = liv wavemode.health = liv
all = All
editor.default = [lightgray]<standard> editor.default = [lightgray]<standard>
details = Detaljer... details = Detaljer...

View File

@@ -498,6 +498,7 @@ waves.units.show = Alle anzeigen
wavemode.counts = Menge wavemode.counts = Menge
wavemode.totals = Gesamtmenge wavemode.totals = Gesamtmenge
wavemode.health = Lebenspunkte wavemode.health = Lebenspunkte
all = All
editor.default = [lightgray]<Standard> editor.default = [lightgray]<Standard>
details = Details details = Details

View File

@@ -495,6 +495,7 @@ waves.units.show = Mostrar todo
wavemode.counts = limitadas wavemode.counts = limitadas
wavemode.totals = totales wavemode.totals = totales
wavemode.health = por salud wavemode.health = por salud
all = All
editor.default = [lightgray]<Por defecto> editor.default = [lightgray]<Por defecto>
details = Detalles... details = Detalles...

View File

@@ -490,6 +490,7 @@ waves.units.show = Show All
wavemode.counts = counts wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<Vaikimisi> editor.default = [lightgray]<Vaikimisi>
details = Üksikasjad... details = Üksikasjad...

View File

@@ -492,6 +492,7 @@ waves.units.show = Show All
wavemode.counts = counts wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<Lehenetsia> editor.default = [lightgray]<Lehenetsia>
details = Xehetasunak... details = Xehetasunak...

View File

@@ -490,6 +490,7 @@ waves.units.show = Näytä kaikki
wavemode.counts = lukumäärä wavemode.counts = lukumäärä
wavemode.totals = yhteismäärä wavemode.totals = yhteismäärä
wavemode.health = elämäpisteet wavemode.health = elämäpisteet
all = All
editor.default = [lightgray]<Oletus> editor.default = [lightgray]<Oletus>
details = Yksityiskohdat... details = Yksityiskohdat...

View File

@@ -490,6 +490,7 @@ waves.units.show = Ipakita lahat
wavemode.counts = counts wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<Default> editor.default = [lightgray]<Default>
details = Details... details = Details...

View File

@@ -501,6 +501,7 @@ waves.units.show = Afficher tout
wavemode.counts = compte wavemode.counts = compte
wavemode.totals = totaux wavemode.totals = totaux
wavemode.health = santé wavemode.health = santé
all = All
editor.default = [lightgray]<par défaut> editor.default = [lightgray]<par défaut>
details = Détails... details = Détails...

View File

@@ -501,6 +501,7 @@ waves.units.show = Összes megjelenítése
wavemode.counts = típusokra bontva wavemode.counts = típusokra bontva
wavemode.totals = összesítés wavemode.totals = összesítés
wavemode.health = életpontok wavemode.health = életpontok
all = All
editor.default = [lightgray]<Alapbeállítás> editor.default = [lightgray]<Alapbeállítás>
details = Részletek... details = Részletek...

View File

@@ -501,6 +501,7 @@ waves.units.show = Perlihatkan Semua
wavemode.counts = jumlah wavemode.counts = jumlah
wavemode.totals = total wavemode.totals = total
wavemode.health = darah wavemode.health = darah
all = All
editor.default = [lightgray]<Standar> editor.default = [lightgray]<Standar>
details = Detail... details = Detail...

View File

@@ -493,6 +493,7 @@ waves.units.show = Mostra tutto
wavemode.counts = conteggi wavemode.counts = conteggi
wavemode.totals = totali wavemode.totals = totali
wavemode.health = salute wavemode.health = salute
all = All
editor.default = [lightgray]<Predefinito> editor.default = [lightgray]<Predefinito>
details = Dettagli... details = Dettagli...

View File

@@ -495,6 +495,7 @@ waves.units.show = すべて表示
wavemode.counts = wavemode.counts =
wavemode.totals = 総数 wavemode.totals = 総数
wavemode.health = 総体力 wavemode.health = 総体力
all = All
editor.default = [lightgray]<デフォルト> editor.default = [lightgray]<デフォルト>
details = 詳細... details = 詳細...

View File

@@ -494,6 +494,7 @@ waves.units.show = 모두 보이기
wavemode.counts = wavemode.counts =
wavemode.totals = wavemode.totals =
wavemode.health = 체력 wavemode.health = 체력
all = All
editor.default = [lightgray]<기본값> editor.default = [lightgray]<기본값>
details = 설명... details = 설명...

View File

@@ -490,6 +490,7 @@ waves.units.show = Show All
wavemode.counts = counts wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<Numatytasis> editor.default = [lightgray]<Numatytasis>
details = Detaliau... details = Detaliau...

View File

@@ -498,6 +498,7 @@ waves.units.show = Toon Alle
wavemode.counts = telt wavemode.counts = telt
wavemode.totals = totalen wavemode.totals = totalen
wavemode.health = levenspunten wavemode.health = levenspunten
all = All
editor.default = [lightgray]<Standaard> editor.default = [lightgray]<Standaard>
details = Details... details = Details...

View File

@@ -490,6 +490,7 @@ waves.units.show = Show All
wavemode.counts = counts wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<Default> editor.default = [lightgray]<Default>
details = Details... details = Details...

View File

@@ -495,6 +495,7 @@ waves.units.show = Pokaż Wszystkie
wavemode.counts = liczba wavemode.counts = liczba
wavemode.totals = sumy wavemode.totals = sumy
wavemode.health = życie wavemode.health = życie
all = All
editor.default = [lightgray]<Domyślne> editor.default = [lightgray]<Domyślne>
details = Detale... details = Detale...

View File

@@ -495,6 +495,7 @@ waves.units.show = Mostrar tudo
wavemode.counts = quantidade wavemode.counts = quantidade
wavemode.totals = total wavemode.totals = total
wavemode.health = vida wavemode.health = vida
all = All
editor.default = [lightgray]<padrão> editor.default = [lightgray]<padrão>
details = Detalhes... details = Detalhes...

View File

@@ -490,6 +490,7 @@ waves.units.show = Show All
wavemode.counts = counts wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<padrão> editor.default = [lightgray]<padrão>
details = Detalhes... details = Detalhes...

View File

@@ -495,6 +495,7 @@ waves.units.show = Vezi Tot
wavemode.counts = numere wavemode.counts = numere
wavemode.totals = totaluri wavemode.totals = totaluri
wavemode.health = viață wavemode.health = viață
all = All
editor.default = [lightgray]<Prestabilit> editor.default = [lightgray]<Prestabilit>
details = Detalii... details = Detalii...

View File

@@ -495,6 +495,7 @@ waves.units.show = Показать все
wavemode.counts = количество единиц wavemode.counts = количество единиц
wavemode.totals = всего единиц wavemode.totals = всего единиц
wavemode.health = всего прочности wavemode.health = всего прочности
all = All
editor.default = [lightgray]<По умолчанию> editor.default = [lightgray]<По умолчанию>
details = Подробности… details = Подробности…

View File

@@ -495,6 +495,7 @@ waves.units.show = Pokaži Sve
wavemode.counts = količina wavemode.counts = količina
wavemode.totals = ukupno wavemode.totals = ukupno
wavemode.health = snaga wavemode.health = snaga
all = All
editor.default = [lightgray]<Default> editor.default = [lightgray]<Default>
details = Detalji... details = Detalji...

View File

@@ -490,6 +490,7 @@ waves.units.show = Show All
wavemode.counts = counts wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<Default> editor.default = [lightgray]<Default>
details = Details... details = Details...

View File

@@ -495,6 +495,7 @@ waves.units.show = แสดงทั้งหมด
wavemode.counts = จำนวน wavemode.counts = จำนวน
wavemode.totals = ทั้งหมด wavemode.totals = ทั้งหมด
wavemode.health = พลังชีวิต wavemode.health = พลังชีวิต
all = All
editor.default = [lightgray]<ค่าเริ่มต้น> editor.default = [lightgray]<ค่าเริ่มต้น>
details = รายละเอียด... details = รายละเอียด...

View File

@@ -490,6 +490,7 @@ waves.units.show = Show All
wavemode.counts = counts wavemode.counts = counts
wavemode.totals = totals wavemode.totals = totals
wavemode.health = health wavemode.health = health
all = All
editor.default = [lightgray]<Default> editor.default = [lightgray]<Default>
details = Details... details = Details...

View File

@@ -495,6 +495,7 @@ waves.units.show = Hepsini Göster
wavemode.counts = miktarlar wavemode.counts = miktarlar
wavemode.totals = toplamlar wavemode.totals = toplamlar
wavemode.health = can wavemode.health = can
all = All
editor.default = [lightgray]<Varsayılan> editor.default = [lightgray]<Varsayılan>
details = Detaylar... details = Detaylar...

View File

@@ -497,6 +497,7 @@ waves.units.show = Показати все
wavemode.counts = кількість wavemode.counts = кількість
wavemode.totals = усього wavemode.totals = усього
wavemode.health = здоров’я wavemode.health = здоров’я
all = All
editor.default = [lightgray]<За замовчуванням> editor.default = [lightgray]<За замовчуванням>
details = Подробиці… details = Подробиці…

View File

@@ -501,6 +501,7 @@ waves.units.show = Hiện tất cả
wavemode.counts = số lượng wavemode.counts = số lượng
wavemode.totals = tổng số wavemode.totals = tổng số
wavemode.health = độ bền wavemode.health = độ bền
all = All
editor.default = [lightgray]<Mặc định> editor.default = [lightgray]<Mặc định>
details = Chi tiết... details = Chi tiết...

View File

@@ -498,6 +498,7 @@ waves.units.show = 全部显示
wavemode.counts = 数目 wavemode.counts = 数目
wavemode.totals = 总数 wavemode.totals = 总数
wavemode.health = 生命值 wavemode.health = 生命值
all = All
editor.default = [lightgray]<默认> editor.default = [lightgray]<默认>
details = 详情… details = 详情…

View File

@@ -495,6 +495,7 @@ waves.units.show = 全部顯示
wavemode.counts = 數量 wavemode.counts = 數量
wavemode.totals = 總數 wavemode.totals = 總數
wavemode.health = 生命值 wavemode.health = 生命值
all = All
editor.default = [lightgray](預設) editor.default = [lightgray](預設)
details = 詳細資訊…… details = 詳細資訊……

View File

@@ -62,7 +62,9 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
} }
long ram = Runtime.getRuntime().maxMemory(); long ram = Runtime.getRuntime().maxMemory();
boolean gb = ram >= 1024 * 1024 * 1024; boolean gb = ram >= 1024 * 1024 * 1024;
Log.info("[RAM] Available: @ @", Strings.fixed(gb ? ram / 1024f / 1024 / 1024f : ram / 1024f / 1024f, 1), gb ? "GB" : "MB"); if(!OS.isIos){
Log.info("[RAM] Available: @ @", Strings.fixed(gb ? ram / 1024f / 1024 / 1024f : ram / 1024f / 1024f, 1), gb ? "GB" : "MB");
}
Time.setDeltaProvider(() -> { Time.setDeltaProvider(() -> {
float result = Core.graphics.getDeltaTime() * 60f; float result = Core.graphics.getDeltaTime() * 60f;

View File

@@ -1513,27 +1513,23 @@ public class Blocks{
requirements(Category.defense, with(Items.copper, 6)); requirements(Category.defense, with(Items.copper, 6));
health = 80 * wallHealthMultiplier; health = 80 * wallHealthMultiplier;
researchCostMultiplier = 0.1f; researchCostMultiplier = 0.1f;
envDisabled |= Env.scorching;
}}; }};
copperWallLarge = new Wall("copper-wall-large"){{ copperWallLarge = new Wall("copper-wall-large"){{
requirements(Category.defense, ItemStack.mult(copperWall.requirements, 4)); requirements(Category.defense, ItemStack.mult(copperWall.requirements, 4));
health = 80 * 4 * wallHealthMultiplier; health = 80 * 4 * wallHealthMultiplier;
size = 2; size = 2;
envDisabled |= Env.scorching;
}}; }};
titaniumWall = new Wall("titanium-wall"){{ titaniumWall = new Wall("titanium-wall"){{
requirements(Category.defense, with(Items.titanium, 6)); requirements(Category.defense, with(Items.titanium, 6));
health = 110 * wallHealthMultiplier; health = 110 * wallHealthMultiplier;
envDisabled |= Env.scorching;
}}; }};
titaniumWallLarge = new Wall("titanium-wall-large"){{ titaniumWallLarge = new Wall("titanium-wall-large"){{
requirements(Category.defense, ItemStack.mult(titaniumWall.requirements, 4)); requirements(Category.defense, ItemStack.mult(titaniumWall.requirements, 4));
health = 110 * wallHealthMultiplier * 4; health = 110 * wallHealthMultiplier * 4;
size = 2; size = 2;
envDisabled |= Env.scorching;
}}; }};
plastaniumWall = new Wall("plastanium-wall"){{ plastaniumWall = new Wall("plastanium-wall"){{
@@ -1542,7 +1538,6 @@ public class Blocks{
insulated = true; insulated = true;
absorbLasers = true; absorbLasers = true;
schematicPriority = 10; schematicPriority = 10;
envDisabled |= Env.scorching;
}}; }};
plastaniumWallLarge = new Wall("plastanium-wall-large"){{ plastaniumWallLarge = new Wall("plastanium-wall-large"){{
@@ -1552,20 +1547,17 @@ public class Blocks{
insulated = true; insulated = true;
absorbLasers = true; absorbLasers = true;
schematicPriority = 10; schematicPriority = 10;
envDisabled |= Env.scorching;
}}; }};
thoriumWall = new Wall("thorium-wall"){{ thoriumWall = new Wall("thorium-wall"){{
requirements(Category.defense, with(Items.thorium, 6)); requirements(Category.defense, with(Items.thorium, 6));
health = 200 * wallHealthMultiplier; health = 200 * wallHealthMultiplier;
envDisabled |= Env.scorching;
}}; }};
thoriumWallLarge = new Wall("thorium-wall-large"){{ thoriumWallLarge = new Wall("thorium-wall-large"){{
requirements(Category.defense, ItemStack.mult(thoriumWall.requirements, 4)); requirements(Category.defense, ItemStack.mult(thoriumWall.requirements, 4));
health = 200 * wallHealthMultiplier * 4; health = 200 * wallHealthMultiplier * 4;
size = 2; size = 2;
envDisabled |= Env.scorching;
}}; }};
phaseWall = new Wall("phase-wall"){{ phaseWall = new Wall("phase-wall"){{
@@ -1573,7 +1565,6 @@ public class Blocks{
health = 150 * wallHealthMultiplier; health = 150 * wallHealthMultiplier;
chanceDeflect = 10f; chanceDeflect = 10f;
flashHit = true; flashHit = true;
envDisabled |= Env.scorching;
}}; }};
phaseWallLarge = new Wall("phase-wall-large"){{ phaseWallLarge = new Wall("phase-wall-large"){{
@@ -1582,14 +1573,12 @@ public class Blocks{
size = 2; size = 2;
chanceDeflect = 10f; chanceDeflect = 10f;
flashHit = true; flashHit = true;
envDisabled |= Env.scorching;
}}; }};
surgeWall = new Wall("surge-wall"){{ surgeWall = new Wall("surge-wall"){{
requirements(Category.defense, with(Items.surgeAlloy, 6)); requirements(Category.defense, with(Items.surgeAlloy, 6));
health = 230 * wallHealthMultiplier; health = 230 * wallHealthMultiplier;
lightningChance = 0.05f; lightningChance = 0.05f;
envDisabled |= Env.scorching;
}}; }};
surgeWallLarge = new Wall("surge-wall-large"){{ surgeWallLarge = new Wall("surge-wall-large"){{
@@ -1597,13 +1586,11 @@ public class Blocks{
health = 230 * 4 * wallHealthMultiplier; health = 230 * 4 * wallHealthMultiplier;
size = 2; size = 2;
lightningChance = 0.05f; lightningChance = 0.05f;
envDisabled |= Env.scorching;
}}; }};
door = new Door("door"){{ door = new Door("door"){{
requirements(Category.defense, with(Items.titanium, 6, Items.silicon, 4)); requirements(Category.defense, with(Items.titanium, 6, Items.silicon, 4));
health = 100 * wallHealthMultiplier; health = 100 * wallHealthMultiplier;
envDisabled |= Env.scorching;
}}; }};
doorLarge = new Door("door-large"){{ doorLarge = new Door("door-large"){{
@@ -1612,14 +1599,12 @@ public class Blocks{
closefx = Fx.doorcloselarge; closefx = Fx.doorcloselarge;
health = 100 * 4 * wallHealthMultiplier; health = 100 * 4 * wallHealthMultiplier;
size = 2; size = 2;
envDisabled |= Env.scorching;
}}; }};
scrapWall = new Wall("scrap-wall"){{ scrapWall = new Wall("scrap-wall"){{
requirements(Category.defense, BuildVisibility.sandboxOnly, with(Items.scrap, 6)); requirements(Category.defense, BuildVisibility.sandboxOnly, with(Items.scrap, 6));
health = 60 * wallHealthMultiplier; health = 60 * wallHealthMultiplier;
variants = 5; variants = 5;
envDisabled |= Env.scorching;
}}; }};
scrapWallLarge = new Wall("scrap-wall-large"){{ scrapWallLarge = new Wall("scrap-wall-large"){{
@@ -1627,7 +1612,6 @@ public class Blocks{
health = 60 * 4 * wallHealthMultiplier; health = 60 * 4 * wallHealthMultiplier;
size = 2; size = 2;
variants = 4; variants = 4;
envDisabled |= Env.scorching;
}}; }};
scrapWallHuge = new Wall("scrap-wall-huge"){{ scrapWallHuge = new Wall("scrap-wall-huge"){{
@@ -1635,21 +1619,18 @@ public class Blocks{
health = 60 * 9 * wallHealthMultiplier; health = 60 * 9 * wallHealthMultiplier;
size = 3; size = 3;
variants = 3; variants = 3;
envDisabled |= Env.scorching;
}}; }};
scrapWallGigantic = new Wall("scrap-wall-gigantic"){{ scrapWallGigantic = new Wall("scrap-wall-gigantic"){{
requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 16)); requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 16));
health = 60 * 16 * wallHealthMultiplier; health = 60 * 16 * wallHealthMultiplier;
size = 4; size = 4;
envDisabled |= Env.scorching;
}}; }};
thruster = new Thruster("thruster"){{ thruster = new Thruster("thruster"){{
requirements(Category.defense, BuildVisibility.sandboxOnly, with(Items.scrap, 96)); requirements(Category.defense, BuildVisibility.sandboxOnly, with(Items.scrap, 96));
health = 55 * 16 * wallHealthMultiplier; health = 55 * 16 * wallHealthMultiplier;
size = 4; size = 4;
envDisabled |= Env.scorching;
}}; }};
berylliumWall = new Wall("beryllium-wall"){{ berylliumWall = new Wall("beryllium-wall"){{

View File

@@ -65,7 +65,6 @@ public class Planets{
clearSectorOnLose = true; clearSectorOnLose = true;
defaultCore = Blocks.coreBastion; defaultCore = Blocks.coreBastion;
iconColor = Color.valueOf("ff9266"); iconColor = Color.valueOf("ff9266");
hiddenItems.addAll(Items.serpuloItems).removeAll(Items.erekirItems);
enemyBuildSpeedMultiplier = 0.4f; enemyBuildSpeedMultiplier = 0.4f;
//TODO disallowed for now //TODO disallowed for now
@@ -152,7 +151,6 @@ public class Planets{
startSector = 15; startSector = 15;
alwaysUnlocked = true; alwaysUnlocked = true;
landCloudColor = Pal.spore.cpy().a(0.5f); landCloudColor = Pal.spore.cpy().a(0.5f);
hiddenItems.addAll(Items.erekirItems).removeAll(Items.serpuloItems);
}}; }};
verilus = makeAsteroid("verlius", sun, Blocks.stoneWall, Blocks.iceWall, 0.5f, 12, 2f, gen -> { verilus = makeAsteroid("verlius", sun, Blocks.stoneWall, Blocks.iceWall, 0.5f, 12, 2f, gen -> {

View File

@@ -139,6 +139,16 @@ public class TechTree{
} }
} }
/** Adds the specified database tab to all the content in this tree. */
public void addDatabaseTab(UnlockableContent tab){
each(node -> node.content.databaseTabs.add(tab));
}
/** Adds the specified planet to the shownPlanets of all the content in this tree. */
public void addPlanet(Planet planet){
each(node -> node.content.shownPlanets.add(planet));
}
public Drawable icon(){ public Drawable icon(){
return icon == null ? new TextureRegionDrawable(content.uiIcon) : icon; return icon == null ? new TextureRegionDrawable(content.uiIcon) : icon;
} }

View File

@@ -88,6 +88,7 @@ public class ContentLoader{
/** Calls Content#init() on everything. Use only after all modules have been created. */ /** Calls Content#init() on everything. Use only after all modules have been created. */
public void init(){ public void init(){
initialize(Content::init); initialize(Content::init);
initialize(Content::postInit);
if(logicVars != null) logicVars.init(); if(logicVars != null) logicVars.init();
Events.fire(new ContentInitEvent()); Events.fire(new ContentInitEvent());
} }

View File

@@ -78,7 +78,7 @@ public class GameState{
} }
public @Nullable Planet getPlanet(){ public @Nullable Planet getPlanet(){
return rules.sector != null ? rules.sector.planet : null; return rules.sector != null ? rules.sector.planet : rules.planet;
} }
public boolean isEditor(){ public boolean isEditor(){

View File

@@ -140,10 +140,6 @@ public class Logic implements ApplicationListener{
core.items.set(item, core.block.itemCapacity); core.items.set(item, core.block.itemCapacity);
} }
} }
//set up hidden items
state.rules.hiddenBuildItems.clear();
state.rules.hiddenBuildItems.addAll(state.rules.sector.planet.hiddenItems);
} }
//save settings //save settings

View File

@@ -158,7 +158,7 @@ public class UI implements ApplicationListener, Loadable{
Core.scene.draw(); Core.scene.draw();
if(Core.input.keyTap(KeyCode.mouseLeft) && Core.scene.hasField()){ if(Core.input.keyTap(KeyCode.mouseLeft) && Core.scene.hasField()){
Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); Element e = Core.scene.getHoverElement();
if(!(e instanceof TextField)){ if(!(e instanceof TextField)){
Core.scene.setKeyboardFocus(null); Core.scene.setKeyboardFocus(null);
} }

View File

@@ -321,8 +321,6 @@ public class World{
state.rules.cloudColor = sector.planet.landCloudColor; state.rules.cloudColor = sector.planet.landCloudColor;
state.rules.env = sector.planet.defaultEnv; state.rules.env = sector.planet.defaultEnv;
state.rules.planet = sector.planet; state.rules.planet = sector.planet;
state.rules.hiddenBuildItems.clear();
state.rules.hiddenBuildItems.addAll(sector.planet.hiddenItems);
sector.planet.applyRules(state.rules); sector.planet.applyRules(state.rules);
sector.info.resources = content.toSeq(); sector.info.resources = content.toSeq();
sector.info.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id))); sector.info.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id)));

View File

@@ -25,6 +25,9 @@ public abstract class Content implements Comparable<Content>{
/** Called after all content and modules are created. Do not use to load regions or texture data! */ /** Called after all content and modules are created. Do not use to load regions or texture data! */
public void init(){} public void init(){}
/** Called after init(). */
public void postInit(){}
/** /**
* Called after all content is created, only on non-headless versions. * Called after all content is created, only on non-headless versions.
* Use for loading regions or other image data. * Use for loading regions or other image data.

View File

@@ -35,8 +35,6 @@ public abstract class UnlockableContent extends MappableContent{
public boolean hideDetails = true; public boolean hideDetails = true;
/** If false, all icon generation is disabled for this content; createIcons is not called. */ /** If false, all icon generation is disabled for this content; createIcons is not called. */
public boolean generateIcons = true; public boolean generateIcons = true;
/** Special logic icon ID. */
public int iconId = 0;
/** How big the content appears in certain selection menus */ /** How big the content appears in certain selection menus */
public float selectionSize = 24f; public float selectionSize = 24f;
/** Icon of the content to use in UI. */ /** Icon of the content to use in UI. */
@@ -45,11 +43,24 @@ public abstract class UnlockableContent extends MappableContent{
public TextureRegion fullIcon; public TextureRegion fullIcon;
/** Override for the full icon. Useful for mod content with duplicate icons. Overrides any other full icon.*/ /** Override for the full icon. Useful for mod content with duplicate icons. Overrides any other full icon.*/
public String fullOverride = ""; public String fullOverride = "";
/** If true, this content will appear in all database tabs. */
public boolean allDatabaseTabs = false;
/**
* Planets that this content is made for. If empty, a planet is decided based on item requirements.
* Currently, this is only meaningful for blocks.
* */
public ObjectSet<Planet> shownPlanets = new ObjectSet<>();
/**
* Content - usually a planet - that dictates which database tab(s) this content will appear in.
* If nothing is defined, it will use the values in shownPlanets.
* If shownPlanets is also empty, it will use Serpulo as the "default" tab.
* */
public ObjectSet<UnlockableContent> databaseTabs = new ObjectSet<>();
/** The tech tree node for this content, if applicable. Null if not part of a tech tree. */ /** The tech tree node for this content, if applicable. Null if not part of a tech tree. */
public @Nullable TechNode techNode; public @Nullable TechNode techNode;
/** Tech nodes for all trees that this content is part of. */ /** Tech nodes for all trees that this content is part of. */
public Seq<TechNode> techNodes = new Seq<>(); public Seq<TechNode> techNodes = new Seq<>();
/** Unlock state. Loaded from settings. Do not modify outside of the constructor. */ /** Unlock state. Loaded from settings. Do not modify outside the constructor. */
protected boolean unlocked; protected boolean unlocked;
public UnlockableContent(String name){ public UnlockableContent(String name){
@@ -61,6 +72,13 @@ public abstract class UnlockableContent extends MappableContent{
this.unlocked = Core.settings != null && Core.settings.getBool(this.name + "-unlocked", false); this.unlocked = Core.settings != null && Core.settings.getBool(this.name + "-unlocked", false);
} }
@Override
public void postInit(){
super.postInit();
databaseTabs.addAll(shownPlanets);
}
@Override @Override
public void loadIcon(){ public void loadIcon(){
fullIcon = fullIcon =
@@ -74,6 +92,10 @@ public abstract class UnlockableContent extends MappableContent{
uiIcon = Core.atlas.find(getContentType().name() + "-" + name + "-ui", fullIcon); uiIcon = Core.atlas.find(getContentType().name() + "-" + name + "-ui", fullIcon);
} }
public boolean isOnPlanet(@Nullable Planet planet){
return planet == null || shownPlanets.isEmpty() || shownPlanets.contains(planet);
}
public int getLogicId(){ public int getLogicId(){
return logicVars.lookupLogicId(this); return logicVars.lookupLogicId(this);
} }

View File

@@ -329,7 +329,7 @@ public class MapView extends Element implements GestureListener{
return Core.scene != null && Core.scene.getKeyboardFocus() != null return Core.scene != null && Core.scene.getKeyboardFocus() != null
&& Core.scene.getKeyboardFocus().isDescendantOf(ui.editor) && Core.scene.getKeyboardFocus().isDescendantOf(ui.editor)
&& ui.editor.isShown() && tool == EditorTool.zoom && && ui.editor.isShown() && tool == EditorTool.zoom &&
Core.scene.hit(Core.input.mouse().x, Core.input.mouse().y, true) == this; Core.scene.getHoverElement() == this;
} }
@Override @Override

View File

@@ -1370,6 +1370,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
/** Called when the block is destroyed. The tile is still intact at this stage. */ /** Called when the block is destroyed. The tile is still intact at this stage. */
public void onDestroyed(){ public void onDestroyed(){
if(sound != null){
sound.stop();
}
float explosiveness = block.baseExplosiveness; float explosiveness = block.baseExplosiveness;
float flammability = 0f; float flammability = 0f;
float power = 0f; float power = 0f;

View File

@@ -153,8 +153,6 @@ public class Rules{
public ObjectSet<Block> revealedBlocks = new ObjectSet<>(); public ObjectSet<Block> revealedBlocks = new ObjectSet<>();
/** Unlocked content names. Only used in multiplayer when the campaign is enabled. */ /** Unlocked content names. Only used in multiplayer when the campaign is enabled. */
public ObjectSet<String> researched = new ObjectSet<>(); public ObjectSet<String> researched = new ObjectSet<>();
/** Block containing these items as requirements are hidden. */
public ObjectSet<Item> hiddenBuildItems = Items.erekirOnlyItems.asSet();
/** In-map objective executor. */ /** In-map objective executor. */
public MapObjectives objectives = new MapObjectives(); public MapObjectives objectives = new MapObjectives();
/** Flags set by objectives. Used in world processors. */ /** Flags set by objectives. Used in world processors. */

View File

@@ -8,6 +8,7 @@ import arc.struct.*;
import arc.util.*; import arc.util.*;
import mindustry.*; import mindustry.*;
import mindustry.ai.*; import mindustry.ai.*;
import mindustry.annotations.Annotations.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
@@ -359,6 +360,10 @@ public class Teams{
//TODO this may cause a lot of packet spam, optimize? //TODO this may cause a lot of packet spam, optimize?
Call.setTeam(build, Team.derelict); Call.setTeam(build, Team.derelict);
if(build.getPayload() instanceof UnitPayload){
Call.destroyPayload(build);
}
if(Mathf.chance(0.25)){ if(Mathf.chance(0.25)){
Time.run(Mathf.random(0f, 60f * 6f), build::kill); Time.run(Mathf.random(0f, 60f * 6f), build::kill);
} }
@@ -425,6 +430,14 @@ public class Teams{
} }
} }
@Remote(called = Loc.server, unreliable = true)
public static void destroyPayload(Building build){
if(build != null && build.getPayload() instanceof UnitPayload && build.takePayload() instanceof UnitPayload unit){
unit.dump();
unit.unit.killed();
}
}
/** Represents a block made by this team that was destroyed somewhere on the map. /** Represents a block made by this team that was destroyed somewhere on the map.
* This does not include deconstructed blocks.*/ * This does not include deconstructed blocks.*/
public static class BlockPlan{ public static class BlockPlan{

View File

@@ -132,7 +132,9 @@ public class GlobalVars{
} }
for(UnitType type : Vars.content.units()){ for(UnitType type : Vars.content.units()){
put("@" + type.name, type); if(!type.internal){
put("@" + type.name, type);
}
} }
for(Weather weather : Vars.content.weathers()){ for(Weather weather : Vars.content.weathers()){

View File

@@ -33,8 +33,9 @@ public class LAssembler{
Seq<LStatement> st = read(data, privileged); Seq<LStatement> st = read(data, privileged);
asm.instructions = st.map(l -> l.build(asm)).retainAll(l -> l != null).toArray(LInstruction.class);
asm.privileged = privileged; asm.privileged = privileged;
asm.instructions = st.map(l -> l.build(asm)).retainAll(l -> l != null).toArray(LInstruction.class);
return asm; return asm;
} }
@@ -58,7 +59,7 @@ public class LAssembler{
/** @return a variable by name. /** @return a variable by name.
* This may be a constant variable referring to a number or object. */ * This may be a constant variable referring to a number or object. */
public LVar var(String symbol){ public LVar var(String symbol){
LVar constVar = Vars.logicVars.get(symbol); LVar constVar = Vars.logicVars.get(symbol, privileged);
if(constVar != null) return constVar; if(constVar != null) return constVar;
symbol = symbol.trim(); symbol = symbol.trim();

View File

@@ -171,7 +171,7 @@ public class LCanvas extends Table{
} }
StatementElem checkHovered(){ StatementElem checkHovered(){
Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); Element e = Core.scene.getHoverElement();
if(e != null){ if(e != null){
while(e != null && !(e instanceof StatementElem)){ while(e != null && !(e instanceof StatementElem)){
e = e.parent; e = e.parent;

View File

@@ -555,7 +555,7 @@ public class LExecutor{
int address = position.numi(); int address = position.numi();
Building from = target.building(); Building from = target.building();
if(from instanceof MemoryBuild mem && (exec.privileged || from.team == exec.team)){ if(from instanceof MemoryBuild mem && (exec.privileged || (from.team == exec.team && !mem.block.privileged))){
output.setnum(address < 0 || address >= mem.memory.length ? 0 : mem.memory[address]); output.setnum(address < 0 || address >= mem.memory.length ? 0 : mem.memory[address]);
} }
} }
@@ -662,7 +662,7 @@ public class LExecutor{
LogicAI ai = null; LogicAI ai = null;
if(base instanceof Ranged r && (exec.privileged || r.team() == exec.team) && if(base instanceof Ranged r && (exec.privileged || r.team() == exec.team) &&
(base instanceof Building || (ai = UnitControlI.checkLogicAI(exec, base)) != null)){ //must be a building or a controllable unit ((base instanceof Building b && (!b.block.privileged || exec.privileged)) || (ai = UnitControlI.checkLogicAI(exec, base)) != null)){ //must be a building or a controllable unit
float range = r.range(); float range = r.range();
Healthc targeted; Healthc targeted;
@@ -1050,7 +1050,7 @@ public class LExecutor{
@Override @Override
public void run(LExecutor exec){ public void run(LExecutor exec){
if(target.building() instanceof MessageBuild d && (d.team == exec.team || exec.privileged)){ if(target.building() instanceof MessageBuild d && (exec.privileged || (d.team == exec.team && !d.block.privileged))){
d.message.setLength(0); d.message.setLength(0);
d.message.append(exec.textBuffer, 0, Math.min(exec.textBuffer.length(), maxTextBuffer)); d.message.append(exec.textBuffer, 0, Math.min(exec.textBuffer.length(), maxTextBuffer));
@@ -1242,7 +1242,8 @@ public class LExecutor{
result.setobj(units == null || i < 0 || i >= units.size ? null : units.get(i)); result.setobj(units == null || i < 0 || i >= units.size ? null : units.get(i));
} }
} }
case player -> result.setobj(i < 0 || i >= data.players.size ? null : data.players.get(i).unit()); case player -> result.setobj(i < 0 || i >= data.players.size ? null :
data.players.get(i).unit() instanceof BlockUnitc block ? block.tile() : data.players.get(i).unit());
case core -> result.setobj(i < 0 || i >= data.cores.size ? null : data.cores.get(i)); case core -> result.setobj(i < 0 || i >= data.cores.size ? null : data.cores.get(i));
case build -> { case build -> {
Block block = extra.obj() instanceof Block b ? b : null; Block block = extra.obj() instanceof Block b ? b : null;
@@ -1295,7 +1296,7 @@ public class LExecutor{
@Override @Override
public void run(LExecutor exec){ public void run(LExecutor exec){
Tile tile = world.tile(x.numi(), y.numi()); Tile tile = world.tile(Mathf.round(x.numf()), Mathf.round(y.numf()));
if(tile == null){ if(tile == null){
dest.setobj(null); dest.setobj(null);
}else{ }else{
@@ -1380,7 +1381,7 @@ public class LExecutor{
Team t = team.team(); Team t = team.team();
if(type.obj() instanceof UnitType type && !type.hidden && t != null && Units.canCreate(t, type)){ if(type.obj() instanceof UnitType type && !type.internal && !type.hidden && t != null && Units.canCreate(t, type)){
//random offset to prevent stacking //random offset to prevent stacking
var unit = type.spawn(t, World.unconv(x.numf()) + Mathf.range(0.01f), World.unconv(y.numf()) + Mathf.range(0.01f)); var unit = type.spawn(t, World.unconv(x.numf()) + Mathf.range(0.01f), World.unconv(y.numf()) + Mathf.range(0.01f));
spawner.spawnEffect(unit, rotation.numf()); spawner.spawnEffect(unit, rotation.numf());

View File

@@ -34,7 +34,7 @@ public class BaseGenerator{
Seq<Block> wallsSmall = content.blocks().select(b -> b instanceof Wall && b.isVanilla() && b.size == size Seq<Block> wallsSmall = content.blocks().select(b -> b instanceof Wall && b.isVanilla() && b.size == size
&& !b.insulated && b.buildVisibility == BuildVisibility.shown && !b.insulated && b.buildVisibility == BuildVisibility.shown
&& !(b instanceof Door) && !(b instanceof Door)
&& !(Structs.contains(b.requirements, i -> state.rules.hiddenBuildItems.contains(i.item)))); && b.isOnPlanet(state.getPlanet()));
wallsSmall.sort(b -> b.buildCost); wallsSmall.sort(b -> b.buildCost);
return wallsSmall.getFrac(difficulty * 0.91f); return wallsSmall.getFrac(difficulty * 0.91f);
} }

View File

@@ -1097,29 +1097,41 @@ public class ContentParser{
} }
Field field = metadata.field; Field field = metadata.field;
try{ try{
boolean isMap = ObjectMap.class.isAssignableFrom(field.getType()) || ObjectIntMap.class.isAssignableFrom(field.getType()) || ObjectFloatMap.class.isAssignableFrom(field.getType()); if(child.isObject() && child.has("add") && (Seq.class.isAssignableFrom(field.getType()) || ObjectSet.class.isAssignableFrom(field.getType()))){
boolean mergeMap = isMap && child.has("add") && child.get("add").isBoolean() && child.getBoolean("add", false); Object readField = parser.readValue(field.getType(), metadata.elementType, child.get("add"), metadata.keyType);
Object fieldObj = field.get(object);
if(mergeMap){ if(fieldObj instanceof ObjectSet set){
child.remove("add"); set.addAll((ObjectSet)readField);
} }else if(fieldObj instanceof Seq seq){
seq.addAll((Seq)readField);
Object readField = parser.readValue(field.getType(), metadata.elementType, child, metadata.keyType); }else{
Object fieldObj = field.get(object); throw new SerializationException("This should be impossible");
//if a map has add: true, add its contents to the map instead
if(mergeMap && (fieldObj instanceof ObjectMap<?,?> || fieldObj instanceof ObjectIntMap<?> || fieldObj instanceof ObjectFloatMap<?>)){
if(field.get(object) instanceof ObjectMap<?,?> baseMap){
baseMap.putAll((ObjectMap)readField);
}else if(field.get(object) instanceof ObjectIntMap<?> baseMap){
baseMap.putAll((ObjectIntMap)readField);
}else if(field.get(object) instanceof ObjectFloatMap<?> baseMap){
baseMap.putAll((ObjectFloatMap)readField);
} }
}else{ }else{
field.set(object, readField); boolean isMap = ObjectMap.class.isAssignableFrom(field.getType()) || ObjectIntMap.class.isAssignableFrom(field.getType()) || ObjectFloatMap.class.isAssignableFrom(field.getType());
} boolean mergeMap = isMap && child.has("add") && child.get("add").isBoolean() && child.getBoolean("add", false);
if(mergeMap){
child.remove("add");
}
Object readField = parser.readValue(field.getType(), metadata.elementType, child, metadata.keyType);
Object fieldObj = field.get(object);
//if a map has add: true, add its contents to the map instead
if(mergeMap && (fieldObj instanceof ObjectMap<?,?> || fieldObj instanceof ObjectIntMap<?> || fieldObj instanceof ObjectFloatMap<?>)){
if(field.get(object) instanceof ObjectMap<?,?> baseMap){
baseMap.putAll((ObjectMap)readField);
}else if(field.get(object) instanceof ObjectIntMap<?> baseMap){
baseMap.putAll((ObjectIntMap)readField);
}else if(field.get(object) instanceof ObjectFloatMap<?> baseMap){
baseMap.putAll((ObjectFloatMap)readField);
}
}else{
field.set(object, readField);
}
}
}catch(IllegalAccessException ex){ }catch(IllegalAccessException ex){
throw new SerializationException("Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex); throw new SerializationException("Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
}catch(SerializationException ex){ }catch(SerializationException ex){

View File

@@ -81,12 +81,12 @@ public class GameService{
} }
private void registerEvents(){ private void registerEvents(){
allTransportSerpulo = content.blocks().select(b -> b.category == Category.distribution && b.isVisibleOn(Planets.serpulo) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class); allTransportSerpulo = content.blocks().select(b -> b.category == Category.distribution && b.isOnPlanet(Planets.serpulo) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
allTransportErekir = content.blocks().select(b -> b.category == Category.distribution && b.isVisibleOn(Planets.erekir) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class); allTransportErekir = content.blocks().select(b -> b.category == Category.distribution && b.isOnPlanet(Planets.erekir) && b.isVanilla() && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
//cores are ignored since they're upgrades and can be skipped //cores are ignored since they're upgrades and can be skipped
allSerpuloBlocks = content.blocks().select(b -> b.synthetic() && b.isVisibleOn(Planets.serpulo) && b.isVanilla() && !(b instanceof CoreBlock) && b.buildVisibility == BuildVisibility.shown).toArray(Block.class); allSerpuloBlocks = content.blocks().select(b -> b.synthetic() && b.isOnPlanet(Planets.serpulo) && b.isVanilla() && !(b instanceof CoreBlock) && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
allErekirBlocks = content.blocks().select(b -> b.synthetic() && b.isVisibleOn(Planets.erekir) && b.isVanilla() && !(b instanceof CoreBlock) && b.buildVisibility == BuildVisibility.shown).toArray(Block.class); allErekirBlocks = content.blocks().select(b -> b.synthetic() && b.isOnPlanet(Planets.erekir) && b.isVanilla() && !(b instanceof CoreBlock) && b.buildVisibility == BuildVisibility.shown).toArray(Block.class);
unitsBuilt = Core.settings.getJson("units-built" , ObjectSet.class, String.class, ObjectSet::new); unitsBuilt = Core.settings.getJson("units-built" , ObjectSet.class, String.class, ObjectSet::new);
blocksBuilt = Core.settings.getJson("blocks-built" , ObjectSet.class, String.class, ObjectSet::new); blocksBuilt = Core.settings.getJson("blocks-built" , ObjectSet.class, String.class, ObjectSet::new);
@@ -526,7 +526,7 @@ public class GameService{
} }
for(Building entity : player.team().cores()){ for(Building entity : player.team().cores()){
if(!content.items().contains(i -> !state.rules.hiddenBuildItems.contains(i) && entity.items.get(i) < entity.block.itemCapacity)){ if(!content.items().contains(i -> i.isOnPlanet(state.getPlanet()) && entity.items.get(i) < entity.block.itemCapacity)){
fillCoreAllCampaign.complete(); fillCoreAllCampaign.complete();
break; break;
} }

View File

@@ -47,7 +47,9 @@ public class Item extends UnlockableContent implements Senseable{
/** If true, this material is used by buildings. If false, this material will be incinerated in certain cores. */ /** If true, this material is used by buildings. If false, this material will be incinerated in certain cores. */
public boolean buildable = true; public boolean buildable = true;
public boolean hidden = false; public boolean hidden = false;
/** For mods. Adds this item to the listed planets' hidden items Seq. */
/** @deprecated no-op, do not use. */
@Deprecated
public @Nullable Planet[] hiddenOnPlanets; public @Nullable Planet[] hiddenOnPlanets;
public Item(String name, Color color){ public Item(String name, Color color){
@@ -60,14 +62,9 @@ public class Item extends UnlockableContent implements Senseable{
} }
@Override @Override
public void init(){ public boolean isOnPlanet(Planet planet){
super.init(); //hidden items should not appear on any planet's resource selection screen
return super.isOnPlanet(planet) && !hidden;
if(hiddenOnPlanets != null){
for(Planet planet : hiddenOnPlanets){
planet.hiddenItems.add(this);
}
}
} }
@Override @Override

View File

@@ -15,7 +15,6 @@ import mindustry.content.*;
import mindustry.content.TechTree.*; import mindustry.content.TechTree.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.game.EventType.ContentInitEvent;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.graphics.g3d.*; import mindustry.graphics.g3d.*;
@@ -146,10 +145,8 @@ public class Planet extends UnlockableContent{
public @Nullable TechNode techTree; public @Nullable TechNode techTree;
/** TODO remove? Planets that can be launched to from this one. Made mutual in init(). */ /** TODO remove? Planets that can be launched to from this one. Made mutual in init(). */
public Seq<Planet> launchCandidates = new Seq<>(); public Seq<Planet> launchCandidates = new Seq<>();
/** Items not available on this planet. Left out for backwards compatibility. */ /** If true, all content in this planet's tech tree will be assigned this planet in their shownPlanets. */
public Seq<Item> hiddenItems = new Seq<>(); public boolean autoAssignPlanet = true;
/** The only items available on this planet, if defined. */
public Seq<Item> itemWhitelist = new Seq<>();
/** Content (usually planet-specific) that is unlocked upon landing here. */ /** Content (usually planet-specific) that is unlocked upon landing here. */
public Seq<UnlockableContent> unlockedOnLand = new Seq<>(); public Seq<UnlockableContent> unlockedOnLand = new Seq<>();
/** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */ /** Loads the mesh. Clientside only. Defaults to a boring sphere mesh. */
@@ -157,6 +154,11 @@ public class Planet extends UnlockableContent{
/** Loads the planet grid outline mesh. Clientside only. */ /** Loads the planet grid outline mesh. Clientside only. */
public Prov<Mesh> gridMeshLoader = () -> MeshBuilder.buildPlanetGrid(grid, outlineColor, outlineRad * radius); public Prov<Mesh> gridMeshLoader = () -> MeshBuilder.buildPlanetGrid(grid, outlineColor, outlineRad * radius);
/** @deprecated no-op, do not use. */
@Deprecated
public Seq<Item> itemWhitelist = new Seq<>(), hiddenItems = new Seq<>();
public Planet(String name, Planet parent, float radius){ public Planet(String name, Planet parent, float radius){
super(name); super(name);
@@ -179,13 +181,6 @@ public class Planet extends UnlockableContent{
parent.updateTotalRadius(); parent.updateTotalRadius();
} }
//if an item whitelist exists, add everything else not in that whitelist to hidden items
Events.on(ContentInitEvent.class, e -> {
if(itemWhitelist.size > 0){
hiddenItems.addAll(content.items().select(i -> !itemWhitelist.contains(i)));
}
});
//calculate solar system //calculate solar system
for(solarSystem = this; solarSystem.parent != null; solarSystem = solarSystem.parent); for(solarSystem = this; solarSystem.parent != null; solarSystem = solarSystem.parent);
} }
@@ -216,8 +211,6 @@ public class Planet extends UnlockableContent{
rules.attributes.add(defaultAttributes); rules.attributes.add(defaultAttributes);
rules.env = defaultEnv; rules.env = defaultEnv;
rules.planet = this; rules.planet = this;
rules.hiddenBuildItems.clear();
rules.hiddenBuildItems.addAll(hiddenItems);
} }
public @Nullable Sector getLastSector(){ public @Nullable Sector getLastSector(){
@@ -338,6 +331,11 @@ public class Planet extends UnlockableContent{
techTree = TechTree.roots.find(n -> n.planet == this); techTree = TechTree.roots.find(n -> n.planet == this);
} }
if(techTree != null && autoAssignPlanet){
techTree.addDatabaseTab(this);
techTree.addPlanet(this);
}
for(Sector sector : sectors){ for(Sector sector : sectors){
sector.loadInfo(); sector.loadInfo();
} }

View File

@@ -68,10 +68,12 @@ public class StatusEffect extends UnlockableContent{
public StatusEffect(String name){ public StatusEffect(String name){
super(name); super(name);
allDatabaseTabs = true;
} }
@Override @Override
public void init(){ public void init(){
super.init();
if(initblock != null){ if(initblock != null){
initblock.run(); initblock.run();
} }

View File

@@ -675,6 +675,8 @@ public class UnitType extends UnlockableContent implements Senseable{
@CallSuper @CallSuper
@Override @Override
public void init(){ public void init(){
super.init();
if(constructor == null) throw new IllegalArgumentException("no constructor set up for unit '" + name + "'"); if(constructor == null) throw new IllegalArgumentException("no constructor set up for unit '" + name + "'");
Unit example = constructor.get(); Unit example = constructor.get();

View File

@@ -111,7 +111,7 @@ public class Minimap extends Table{
update(() -> { update(() -> {
Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); Element e = Core.scene.getHoverElement();
if(e != null && e.isDescendantOf(this)){ if(e != null && e.isDescendantOf(this)){
requestScroll(); requestScroll();
}else if(hasScroll()){ }else if(hasScroll()){

View File

@@ -229,19 +229,8 @@ public class CustomRulesDialog extends BaseDialog{
} }
number("@rules.dropzoneradius", false, f -> rules.dropZoneRadius = f * tilesize, () -> rules.dropZoneRadius / tilesize, () -> rules.waves); number("@rules.dropzoneradius", false, f -> rules.dropZoneRadius = f * tilesize, () -> rules.dropZoneRadius / tilesize, () -> rules.waves);
category("resourcesbuilding"); category("resourcesbuilding");
check("@rules.infiniteresources", b -> { check("@rules.infiniteresources", b -> rules.infiniteResources = b, () -> rules.infiniteResources);
rules.infiniteResources = b;
//reset to serpulo if any env was enabled
if(!b && rules.hiddenBuildItems.isEmpty()){
rules.env = Planets.serpulo.defaultEnv;
rules.hiddenBuildItems.clear();
rules.hiddenBuildItems.addAll(Planets.serpulo.hiddenItems);
setup();
}
}, () -> rules.infiniteResources);
check("@rules.onlydepositcore", b -> rules.onlyDepositCore = b, () -> rules.onlyDepositCore); check("@rules.onlydepositcore", b -> rules.onlyDepositCore = b, () -> rules.onlyDepositCore);
check("@rules.derelictrepair", b -> rules.derelictRepair = b, () -> rules.derelictRepair); check("@rules.derelictrepair", b -> rules.derelictRepair = b, () -> rules.derelictRepair);
check("@rules.reactorexplosions", b -> rules.reactorExplosions = b, () -> rules.reactorExplosions); check("@rules.reactorexplosions", b -> rules.reactorExplosions = b, () -> rules.reactorExplosions);
@@ -349,7 +338,6 @@ public class CustomRulesDialog extends BaseDialog{
t.button("@rules.anyenv", style, () -> { t.button("@rules.anyenv", style, () -> {
rules.env = Vars.defaultEnv; rules.env = Vars.defaultEnv;
rules.hiddenBuildItems.clear();
rules.planet = Planets.sun; rules.planet = Planets.sun;
}).group(group).checked(b -> rules.planet == Planets.sun); }).group(group).checked(b -> rules.planet == Planets.sun);
}).left().fill(false).expand(false, false).row(); }).left().fill(false).expand(false, false).row();

View File

@@ -5,11 +5,13 @@ import arc.graphics.*;
import arc.input.*; import arc.input.*;
import arc.math.*; import arc.math.*;
import arc.scene.event.*; import arc.scene.event.*;
import arc.scene.style.*;
import arc.scene.ui.*; import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import mindustry.*; import mindustry.*;
import mindustry.content.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
@@ -24,16 +26,30 @@ public class DatabaseDialog extends BaseDialog{
private TextField search; private TextField search;
private Table all = new Table(); private Table all = new Table();
private @Nullable Seq<UnlockableContent> allTabs;
//sun means "all content"
private UnlockableContent tab = Planets.sun;
public DatabaseDialog(){ public DatabaseDialog(){
super("@database"); super("@database");
shouldPause = true; shouldPause = true;
addCloseButton(); addCloseButton();
shown(this::rebuild); shown(() -> {
checkTabList();
if(state.isCampaign() && allTabs.contains(state.getPlanet())){
tab = state.getPlanet();
}else if(state.isGame() && state.rules.planet != null && allTabs.contains(state.rules.planet)){
tab = state.rules.planet;
}
rebuild();
});
onResize(this::rebuild); onResize(this::rebuild);
all.margin(20).marginTop(0f); all.margin(20).marginTop(0f);
cont.top();
cont.table(s -> { cont.table(s -> {
s.image(Icon.zoom).padRight(8); s.image(Icon.zoom).padRight(8);
search = s.field(null, text -> rebuild()).growX().get(); search = s.field(null, text -> rebuild()).growX().get();
@@ -43,18 +59,51 @@ public class DatabaseDialog extends BaseDialog{
cont.pane(all).scrollX(false); cont.pane(all).scrollX(false);
} }
void checkTabList(){
if(allTabs == null){
Seq<Content>[] allContent = Vars.content.getContentMap();
ObjectSet<UnlockableContent> all = new ObjectSet<>();
for(var contents : allContent){
for(var content : contents){
if(content instanceof UnlockableContent u){
all.addAll(u.databaseTabs);
}
}
}
allTabs = all.toSeq().sort();
allTabs.insert(0, Planets.sun);
}
}
void rebuild(){ void rebuild(){
checkTabList();
all.clear(); all.clear();
var text = search.getText().toLowerCase(); var text = search.getText().toLowerCase();
Seq<Content>[] allContent = Vars.content.getContentMap(); Seq<Content>[] allContent = Vars.content.getContentMap();
all.table(t -> {
int i = 0;
for(var content : allTabs){
t.button(content == Planets.sun ? Icon.eyeSmall : content instanceof Planet ? Icon.planet : new TextureRegionDrawable(content.uiIcon), Styles.clearNoneTogglei, iconMed, () -> {
tab = content;
rebuild();
}).size(50f).checked(b -> tab == content).tooltip(content == Planets.sun ? "@all" : content.localizedName).with(but -> {
but.getStyle().imageUpColor = content instanceof Planet p ? p.iconColor : Color.white.cpy();
});
if(++i % 10 == 0) t.row();
}
}).row();;
for(int j = 0; j < allContent.length; j++){ for(int j = 0; j < allContent.length; j++){
ContentType type = ContentType.all[j]; ContentType type = ContentType.all[j];
Seq<UnlockableContent> array = allContent[j] Seq<UnlockableContent> array = allContent[j]
.select(c -> c instanceof UnlockableContent u && !u.isHidden() && .select(c -> c instanceof UnlockableContent u && !u.isHidden() && (tab == Planets.sun || u.allDatabaseTabs || u.databaseTabs.contains(tab)) &&
(text.isEmpty() || u.localizedName.toLowerCase().contains(text))).as(); (text.isEmpty() || u.localizedName.toLowerCase().contains(text))).as();
if(array.size == 0) continue; if(array.size == 0) continue;
all.add("@content." + type.name() + ".name").growX().left().color(Pal.accent); all.add("@content." + type.name() + ".name").growX().left().color(Pal.accent);

View File

@@ -48,7 +48,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
ItemSeq launch = universe.getLaunchResources(); ItemSeq launch = universe.getLaunchResources();
if(sector.planet.allowLaunchLoadout){ if(sector.planet.allowLaunchLoadout){
for(var item : content.items()){ for(var item : content.items()){
if(sector.planet.hiddenItems.contains(item)){ if(!item.isOnPlanet(sector.planet)){
launch.set(item, 0); launch.set(item, 0);
} }
} }
@@ -72,7 +72,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
if(destination.preset != null){ if(destination.preset != null){
var rules = destination.preset.generator.map.rules(); var rules = destination.preset.generator.map.rules();
for(var stack : rules.loadout){ for(var stack : rules.loadout){
if(!sector.planet.hiddenItems.contains(stack.item)){ if(stack.item.isOnPlanet(sector.planet)){
resources.add(stack.item, stack.amount); resources.add(stack.item, stack.amount);
} }
} }
@@ -136,7 +136,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
ItemSeq realItems = sitems.copy(); ItemSeq realItems = sitems.copy();
selected.requirements().each(realItems::remove); selected.requirements().each(realItems::remove);
loadout.show(lastCapacity, realItems, out, i -> i.unlocked() && !sector.planet.hiddenItems.contains(i), out::clear, () -> {}, () -> { loadout.show(lastCapacity, realItems, out, i -> i.unlocked() && i.isOnPlanet(sector.planet), out::clear, () -> {}, () -> {
universe.updateLaunchResources(new ItemSeq(out)); universe.updateLaunchResources(new ItemSeq(out));
update.run(); update.run();
rebuildItems.run(); rebuildItems.run();
@@ -172,7 +172,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
Cons<Schematic> handler = s -> { Cons<Schematic> handler = s -> {
if(s.tiles.contains(tile -> !tile.block.supportsEnv(sector.planet.defaultEnv) || if(s.tiles.contains(tile -> !tile.block.supportsEnv(sector.planet.defaultEnv) ||
//make sure block can be built here. //make sure block can be built here.
(!sector.planet.hiddenItems.isEmpty() && Structs.contains(tile.block.requirements, stack -> sector.planet.hiddenItems.contains(stack.item))))){ !tile.block.isOnPlanet(sector.planet))){
return; return;
} }

View File

@@ -587,7 +587,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
@Override @Override
public void act(float delta){ public void act(float delta){
if(scene.getDialog() == PlanetDialog.this && !scene.hit(input.mouseX(), input.mouseY(), true).isDescendantOf(e -> e instanceof ScrollPane)){ if(scene.getDialog() == PlanetDialog.this && (scene.getHoverElement() == null || !scene.getHoverElement().isDescendantOf(e -> e instanceof ScrollPane))){
scene.setScrollFocus(PlanetDialog.this); scene.setScrollFocus(PlanetDialog.this);
} }

View File

@@ -472,7 +472,7 @@ public class ResearchDialog extends BaseDialog{
if(mobile){ if(mobile){
tapped(() -> { tapped(() -> {
Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); Element e = Core.scene.getHoverElement();
if(e == this){ if(e == this){
hoverNode = null; hoverNode = null;
rebuild(); rebuild();

View File

@@ -67,7 +67,7 @@ public class BlockConfigFragment{
} }
public boolean hasConfigMouse(){ public boolean hasConfigMouse(){
Element e = Core.scene.hit(Core.input.mouseX(), Core.graphics.getHeight() - Core.input.mouseY(), true); Element e = Core.scene.getHoverElement();
return e != null && (e == table || e.isDescendantOf(table)); return e != null && (e == table || e.isDescendantOf(table));
} }

View File

@@ -615,7 +615,7 @@ public class PlacementFragment{
blocksSelect.margin(4).marginTop(0); blocksSelect.margin(4).marginTop(0);
blockPane = blocksSelect.pane(blocks -> blockTable = blocks).height(194f).update(pane -> { blockPane = blocksSelect.pane(blocks -> blockTable = blocks).height(194f).update(pane -> {
if(pane.hasScroll()){ if(pane.hasScroll()){
Element result = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); Element result = Core.scene.getHoverElement();
if(result == null || !result.isDescendantOf(pane)){ if(result == null || !result.isDescendantOf(pane)){
Core.scene.setScrollFocus(null); Core.scene.setScrollFocus(null);
} }

View File

@@ -899,10 +899,6 @@ public class Block extends UnlockableContent implements Senseable{
return !isHidden() && (state.rules.editor || (!state.rules.hideBannedBlocks || !state.rules.isBanned(this))); return !isHidden() && (state.rules.editor || (!state.rules.hideBannedBlocks || !state.rules.isBanned(this)));
} }
public boolean isVisibleOn(Planet planet){
return !Structs.contains(requirements, i -> planet.hiddenItems.contains(i.item));
}
public boolean isPlaceable(){ public boolean isPlaceable(){
return isVisible() && (!state.rules.isBanned(this) || state.rules.editor) && supportsEnv(state.rules.env); return isVisible() && (!state.rules.isBanned(this) || state.rules.editor) && supportsEnv(state.rules.env);
} }
@@ -948,7 +944,7 @@ public class Block extends UnlockableContent implements Senseable{
} }
public boolean environmentBuildable(){ public boolean environmentBuildable(){
return (state.rules.hiddenBuildItems.isEmpty() || !Structs.contains(requirements, i -> state.rules.hiddenBuildItems.contains(i.item))); return isOnPlanet(state.getPlanet());
} }
public boolean isStatic(){ public boolean isStatic(){
@@ -1164,10 +1160,28 @@ public class Block extends UnlockableContent implements Senseable{
return buildVisibility != BuildVisibility.hidden; return buildVisibility != BuildVisibility.hidden;
} }
@Override
public void postInit(){
//usually, an empty set of planets is a configuration error. auto-assign based on requirements
if(requirements.length > 0 && shownPlanets.isEmpty()){
for(Planet planet : content.planets()){
if(planet.isLandable()){
if(!Structs.contains(requirements, s -> !s.item.isOnPlanet(planet))){
shownPlanets.add(planet);
}
}
}
}
super.postInit();
}
/** Called after all blocks are created. */ /** Called after all blocks are created. */
@Override @Override
@CallSuper @CallSuper
public void init(){ public void init(){
super.init();
//disable standard shadow //disable standard shadow
if(customShadow){ if(customShadow){
hasShadow = false; hasShadow = false;

View File

@@ -9,7 +9,6 @@ import arc.struct.*;
import arc.util.*; import arc.util.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.type.*;
import mindustry.ui.*; import mindustry.ui.*;
import mindustry.world.*; import mindustry.world.*;
@@ -65,7 +64,7 @@ public class ItemSelection{
Seq<T> list = items.select(u -> (text.isEmpty() || u.localizedName.toLowerCase().contains(text.toLowerCase()))); Seq<T> list = items.select(u -> (text.isEmpty() || u.localizedName.toLowerCase().contains(text.toLowerCase())));
for(T item : list){ for(T item : list){
if(!item.unlockedNow() || (item instanceof Item checkVisible && state.rules.hiddenBuildItems.contains(checkVisible)) || item.isHidden()) continue; if(!item.unlockedNow() || !item.isOnPlanet(state.getPlanet()) || item.isHidden()) continue;
ImageButton button = cont.button(Tex.whiteui, Styles.clearNoneTogglei, Mathf.clamp(item.selectionSize, 0f, 40f), () -> { ImageButton button = cont.button(Tex.whiteui, Styles.clearNoneTogglei, Mathf.clamp(item.selectionSize, 0f, 40f), () -> {
if(closeSelect) control.input.config.hideConfig(); if(closeSelect) control.input.config.hideConfig();

View File

@@ -6,6 +6,7 @@ import arc.graphics.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*;
import arc.util.*; import arc.util.*;
import arc.util.io.*; import arc.util.io.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
@@ -266,6 +267,14 @@ public class ForceProjector extends Block{
Draw.reset(); Draw.reset();
} }
@Override
public void overwrote(Seq<Building> previous){
if(previous.size > 0 && previous.first().block == block && previous.first() instanceof ForceBuild b){
broken = b.broken;
buildup = b.buildup;
}
}
@Override @Override
public void write(Writes write){ public void write(Writes write){
super.write(write); super.write(write);

View File

@@ -53,6 +53,7 @@ public class BuildPayload implements Payload{
@Override @Override
public void destroyed(){ public void destroyed(){
build.dead = true;
build.onDestroyed(); build.onDestroyed();
} }

View File

@@ -26,4 +26,4 @@ org.gradle.caching=true
org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000 org.gradle.internal.http.connectionTimeout=100000
android.enableR8.fullMode=false android.enableR8.fullMode=false
archash=3f26197a0c archash=aafecc8a29125e70255e6cdb34a92690531d1a57

View File

@@ -1,4 +1,8 @@
[ [
{
"name": "EscoCorp",
"address": ["81.30.105.171:6567"]
},
{ {
"name": "Redundancy Dept", "name": "Redundancy Dept",
"address": ["min7.include-once.org:8000", "min7.include-once.org:8001"] "address": ["min7.include-once.org:8000", "min7.include-once.org:8001"]
@@ -73,7 +77,7 @@
}, },
{ {
"name": "SMoke of Anarchy", "name": "SMoke of Anarchy",
"address": ["86.102.97.27"] "address": ["mindustry.smokeofanarchy.ru", "mindustry.smokeofanarchy.ru:6568", "mindustry.smokeofanarchy.ru:6569", "mindustry.smokeofanarchy.ru:6570", "mindustry.smokeofanarchy.ru:6571", "mindustry.smokeofanarchy.ru:6572", "mindustry.smokeofanarchy.ru:6573", "mindustry.smokeofanarchy.ru:6574", "mindustry.smokeofanarchy.ru:6575", "mindustry.smokeofanarchy.ru:6576"]
}, },
{ {
"name": "Mindustry.pl", "name": "Mindustry.pl",
@@ -246,7 +250,7 @@
}, },
{ {
"name": "abcxyz remaster", "name": "abcxyz remaster",
"address": ["144.76.57.59:30302", "23.88.73.88:16895"] "address": ["144.76.57.59:35150", "23.88.73.88:11066", "23.88.73.88:9171", "23.88.73.88:10911"]
}, },
{ {
"name": "CroCraft Network", "name": "CroCraft Network",
@@ -282,11 +286,11 @@
}, },
{ {
"name": "AZDustry", "name": "AZDustry",
"address": ["8.245.23.28:25874"] "address": ["148.251.77.197:2012"]
}, },
{ {
"name": "Erepulo", "name": "Erepulo",
"address": ["95.84.198.97:5401", "95.84.198.97:5402", "95.84.198.97:5403", "95.84.198.97:5404", "95.84.198.97:2357", "95.84.198.97:5500"] "address": ["95.84.198.97:5401", "95.84.198.97:5402", "95.84.198.97:5403", "95.84.198.97:5404", "95.84.198.97:2357", "95.84.198.97:5500", "199.83.103.251"]
}, },
{ {
"name": "MineCore", "name": "MineCore",