Compare commits
116 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d8479355c | ||
|
|
86c702861e | ||
|
|
47ec13eef4 | ||
|
|
d8cd0d867c | ||
|
|
d5ede6b1bb | ||
|
|
fd931564aa | ||
|
|
6b19178a13 | ||
|
|
64acd6c1e4 | ||
|
|
560914bebe | ||
|
|
2edec90dfb | ||
|
|
10c1305eae | ||
|
|
852c98f004 | ||
|
|
292f771eb1 | ||
|
|
1acc771edc | ||
|
|
ee61d0dcfa | ||
|
|
e5f2073de2 | ||
|
|
816be9e9bd | ||
|
|
2107af1f0f | ||
|
|
3bb85b4bda | ||
|
|
e86a3e9d09 | ||
|
|
957426c27f | ||
|
|
8bc90a19d2 | ||
|
|
668144cf2a | ||
|
|
c5ed056601 | ||
|
|
ea9d415b92 | ||
|
|
c181204700 | ||
|
|
ca78cb1a3f | ||
|
|
fdafa0933f | ||
|
|
ae92813169 | ||
|
|
8a248dc787 | ||
|
|
f90f611a6d | ||
|
|
1c0d148607 | ||
|
|
95c8b7ae60 | ||
|
|
25d013b768 | ||
|
|
9de8c4d8ac | ||
|
|
7e4ffe6a7d | ||
|
|
b90372a226 | ||
|
|
9adbfcac0f | ||
|
|
d1eb7743ad | ||
|
|
fc3352bcb1 | ||
|
|
9b3360d932 | ||
|
|
3784bfac77 | ||
|
|
54754cd177 | ||
|
|
c48034e420 | ||
|
|
3299279c89 | ||
|
|
a6c3ebc467 | ||
|
|
9f510f61c7 | ||
|
|
3ae48b8753 | ||
|
|
f41725b8dc | ||
|
|
115df3aedd | ||
|
|
3c136ad0ba | ||
|
|
48ee3d255d | ||
|
|
b05f867800 | ||
|
|
55b790a0d4 | ||
|
|
57f6c9dfd9 | ||
|
|
2f9c95afd0 | ||
|
|
4fe1457d96 | ||
|
|
2589a27cb5 | ||
|
|
8704e14fd7 | ||
|
|
2b17dbe390 | ||
|
|
919012608a | ||
|
|
5675a5b035 | ||
|
|
6724752980 | ||
|
|
0e078a9c60 | ||
|
|
c0b1dfc55a | ||
|
|
3d201f7042 | ||
|
|
f1a5aae30a | ||
|
|
9142da2b70 | ||
|
|
022c76bf45 | ||
|
|
bc6db72df0 | ||
|
|
d512aa5b21 | ||
|
|
7cdf7a21fe | ||
|
|
9a5a6e1ce2 | ||
|
|
5a258d2830 | ||
|
|
96ee32f8ed | ||
|
|
a667a94c8e | ||
|
|
d0572a2a0d | ||
|
|
47eea79b60 | ||
|
|
03b37235b3 | ||
|
|
6969fbb1e7 | ||
|
|
ccc59aa61b | ||
|
|
c658865907 | ||
|
|
a13d51e09a | ||
|
|
f827337259 | ||
|
|
b83c76f728 | ||
|
|
5666fd4999 | ||
|
|
5930e3c350 | ||
|
|
4630e5b3a4 | ||
|
|
f16990edcb | ||
|
|
13896589c2 | ||
|
|
8b5cf5309a | ||
|
|
baedba0d5b | ||
|
|
9f926ef71e | ||
|
|
18a3f8bb68 | ||
|
|
623b7ada11 | ||
|
|
6b6d52e2fd | ||
|
|
fc91b6b135 | ||
|
|
f9c33453f2 | ||
|
|
ad4650f408 | ||
|
|
8ca08a0f14 | ||
|
|
792fdef95d | ||
|
|
457514a2c8 | ||
|
|
027d080c55 | ||
|
|
bf8f059c25 | ||
|
|
a73165353f | ||
|
|
613b5a7703 | ||
|
|
988791f18d | ||
|
|
1fb608220f | ||
|
|
56b87a2141 | ||
|
|
3aee9bddd4 | ||
|
|
65f97edbc5 | ||
|
|
d393230add | ||
|
|
75d2b0fb69 | ||
|
|
0cc9b0b0a3 | ||
|
|
9b6c125233 | ||
|
|
1f2b331bf6 |
33
.github/workflows/deployment.yml
vendored
33
.github/workflows/deployment.yml
vendored
@@ -17,21 +17,6 @@ jobs:
|
|||||||
java-version: 14
|
java-version: 14
|
||||||
- name: Set env
|
- name: Set env
|
||||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
- name: Create artifacts
|
|
||||||
run: |
|
|
||||||
./gradlew desktop:dist server:dist core:javadoc -Pbuildversion=${RELEASE_VERSION:1}
|
|
||||||
- name: Update docs
|
|
||||||
run: |
|
|
||||||
cd ../
|
|
||||||
git config --global user.email "cli@github.com"
|
|
||||||
git config --global user.name "Github Actions"
|
|
||||||
git clone --depth=1 https://github.com/MindustryGame/docs.git
|
|
||||||
cp -a Mindustry/core/build/docs/javadoc/. docs/
|
|
||||||
cd docs
|
|
||||||
git add .
|
|
||||||
git commit -m "Update ${RELEASE_VERSION:1}"
|
|
||||||
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs
|
|
||||||
cd ../Mindustry
|
|
||||||
- name: Add Arc release
|
- name: Add Arc release
|
||||||
run: |
|
run: |
|
||||||
git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc
|
git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc
|
||||||
@@ -39,6 +24,24 @@ jobs:
|
|||||||
git tag ${RELEASE_VERSION}
|
git tag ${RELEASE_VERSION}
|
||||||
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/Arc ${RELEASE_VERSION};
|
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/Arc ${RELEASE_VERSION};
|
||||||
cd ../Mindustry
|
cd ../Mindustry
|
||||||
|
- name: Create artifacts
|
||||||
|
run: |
|
||||||
|
./gradlew desktop:dist server:dist core:mergedJavadoc -Pbuildversion=${RELEASE_VERSION:1}
|
||||||
|
- name: Update docs
|
||||||
|
run: |
|
||||||
|
cd ../
|
||||||
|
git config --global user.email "cli@github.com"
|
||||||
|
git config --global user.name "Github Actions"
|
||||||
|
git clone --depth=1 https://github.com/MindustryGame/docs.git
|
||||||
|
cd docs
|
||||||
|
find . -maxdepth 1 ! -name ".git" ! -name . -exec rm -r {} \;
|
||||||
|
cd ../
|
||||||
|
cp -a Mindustry/core/build/javadoc/. docs/
|
||||||
|
cd docs
|
||||||
|
git add .
|
||||||
|
git commit -m "Update ${RELEASE_VERSION:1}"
|
||||||
|
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/MindustryGame/docs
|
||||||
|
cd ../Mindustry
|
||||||
- name: Update F-Droid build string
|
- name: Update F-Droid build string
|
||||||
run: |
|
run: |
|
||||||
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -43,6 +43,7 @@ ios/robovm.properties
|
|||||||
packr-out/
|
packr-out/
|
||||||
config/
|
config/
|
||||||
*.gif
|
*.gif
|
||||||
|
/tests/out
|
||||||
|
|
||||||
/core/assets/basepartnames
|
/core/assets/basepartnames
|
||||||
version.properties
|
version.properties
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ buildscript{
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
jcenter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
@@ -20,8 +19,8 @@ configurations{ natives }
|
|||||||
|
|
||||||
repositories{
|
repositories{
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
|
||||||
maven{ url "https://maven.google.com" }
|
maven{ url "https://maven.google.com" }
|
||||||
|
jcenter() //remove later once google fixes the dependency
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
|
|||||||
29
build.gradle
29
build.gradle
@@ -12,7 +12,6 @@ buildscript{
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
jcenter()
|
|
||||||
maven{ url 'https://jitpack.io' }
|
maven{ url 'https://jitpack.io' }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +183,6 @@ allprojects{
|
|||||||
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
maven{ url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
maven{ url "https://oss.sonatype.org/content/repositories/releases/" }
|
maven{ url "https://oss.sonatype.org/content/repositories/releases/" }
|
||||||
maven{ url 'https://jitpack.io' }
|
maven{ url 'https://jitpack.io' }
|
||||||
jcenter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task clearCache{
|
task clearCache{
|
||||||
@@ -320,6 +318,11 @@ project(":core"){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar, dependsOn: classes){
|
||||||
|
classifier = 'sources'
|
||||||
|
from sourceSets.main.allSource
|
||||||
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
compileJava.dependsOn(preGen)
|
compileJava.dependsOn(preGen)
|
||||||
|
|
||||||
@@ -337,6 +340,28 @@ project(":core"){
|
|||||||
annotationProcessor 'com.github.Anuken:jabel:34e4c172e65b3928cd9eabe1993654ea79c409cd'
|
annotationProcessor 'com.github.Anuken:jabel:34e4c172e65b3928cd9eabe1993654ea79c409cd'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afterEvaluate{
|
||||||
|
task mergedJavadoc(type: Javadoc){
|
||||||
|
def blacklist = [project(":ios"), project(":desktop"), project(":server"), project(":annotations")]
|
||||||
|
if(findProject(":android") != null){
|
||||||
|
blacklist += project(":android")
|
||||||
|
}
|
||||||
|
|
||||||
|
source rootProject.subprojects.collect{ project ->
|
||||||
|
if(!blacklist.contains(project) && project.hasProperty("sourceSets")){
|
||||||
|
return project.sourceSets.main.allJava
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classpath = files(rootProject.subprojects.collect { project ->
|
||||||
|
if(!blacklist.contains(project) && project.hasProperty("sourceSets")){
|
||||||
|
return project.sourceSets.main.compileClasspath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
destinationDir = new File(buildDir, 'javadoc')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project(":server"){
|
project(":server"){
|
||||||
|
|||||||
@@ -41,10 +41,13 @@ be.ignore = Ignore
|
|||||||
be.noupdates = No updates found.
|
be.noupdates = No updates found.
|
||||||
be.check = Check for updates
|
be.check = Check for updates
|
||||||
|
|
||||||
mod.featured.dialog.title = Mod Browser (WIP)
|
mods.browser = Mod Browser
|
||||||
mods.browser.selected = Selected mod
|
mods.browser.selected = Selected mod
|
||||||
mods.browser.add = Install
|
mods.browser.add = Install
|
||||||
mods.github.open = View
|
mods.browser.reinstall = Reinstall
|
||||||
|
mods.github.open = Repo
|
||||||
|
mods.browser.sortdate = Sort by recent
|
||||||
|
mods.browser.sortstars = Sort by stars
|
||||||
|
|
||||||
schematic = Schematic
|
schematic = Schematic
|
||||||
schematic.add = Save Schematic...
|
schematic.add = Save Schematic...
|
||||||
@@ -116,8 +119,10 @@ mods.none = [lightgray]No mods found!
|
|||||||
mods.guide = Modding Guide
|
mods.guide = Modding Guide
|
||||||
mods.report = Report Bug
|
mods.report = Report Bug
|
||||||
mods.openfolder = Open Folder
|
mods.openfolder = Open Folder
|
||||||
|
mods.viewcontent = View Content
|
||||||
mods.reload = Reload
|
mods.reload = Reload
|
||||||
mods.reloadexit = The game will now exit, to reload mods.
|
mods.reloadexit = The game will now exit, to reload mods.
|
||||||
|
mod.installed = [[Installed]
|
||||||
mod.display = [gray]Mod:[orange] {0}
|
mod.display = [gray]Mod:[orange] {0}
|
||||||
mod.enabled = [lightgray]Enabled
|
mod.enabled = [lightgray]Enabled
|
||||||
mod.disabled = [scarlet]Disabled
|
mod.disabled = [scarlet]Disabled
|
||||||
@@ -307,6 +312,7 @@ cancelbuilding = [accent][[{0}][] to clear plan
|
|||||||
selectschematic = [accent][[{0}][] to select+copy
|
selectschematic = [accent][[{0}][] to select+copy
|
||||||
pausebuilding = [accent][[{0}][] to pause building
|
pausebuilding = [accent][[{0}][] to pause building
|
||||||
resumebuilding = [scarlet][[{0}][] to resume building
|
resumebuilding = [scarlet][[{0}][] to resume building
|
||||||
|
enablebuilding = [scarlet][[{0}][] to enable building
|
||||||
showui = UI hidden.\nPress [accent][[{0}][] to show UI.
|
showui = UI hidden.\nPress [accent][[{0}][] to show UI.
|
||||||
wave = [accent]Wave {0}
|
wave = [accent]Wave {0}
|
||||||
wave.cap = [accent]Wave {0}/{1}
|
wave.cap = [accent]Wave {0}/{1}
|
||||||
@@ -678,6 +684,7 @@ stat.drillspeed = Base Drill Speed
|
|||||||
stat.boosteffect = Boost Effect
|
stat.boosteffect = Boost Effect
|
||||||
stat.maxunits = Max Active Units
|
stat.maxunits = Max Active Units
|
||||||
stat.health = Health
|
stat.health = Health
|
||||||
|
stat.armor = Armor
|
||||||
stat.buildtime = Build Time
|
stat.buildtime = Build Time
|
||||||
stat.maxconsecutive = Max Consecutive
|
stat.maxconsecutive = Max Consecutive
|
||||||
stat.buildcost = Build Cost
|
stat.buildcost = Build Cost
|
||||||
@@ -693,6 +700,7 @@ stat.lightningchance = Lightning Chance
|
|||||||
stat.lightningdamage = Lightning Damage
|
stat.lightningdamage = Lightning Damage
|
||||||
stat.flammability = Flammability
|
stat.flammability = Flammability
|
||||||
stat.radioactivity = Radioactivity
|
stat.radioactivity = Radioactivity
|
||||||
|
stat.charge = Charge
|
||||||
stat.heatcapacity = Heat Capacity
|
stat.heatcapacity = Heat Capacity
|
||||||
stat.viscosity = Viscosity
|
stat.viscosity = Viscosity
|
||||||
stat.temperature = Temperature
|
stat.temperature = Temperature
|
||||||
|
|||||||
@@ -41,10 +41,13 @@ be.ignore = Ignorieren
|
|||||||
be.noupdates = Keine Aktualisierungen gefunden.
|
be.noupdates = Keine Aktualisierungen gefunden.
|
||||||
be.check = Auf Aktualisierungen prüfen
|
be.check = Auf Aktualisierungen prüfen
|
||||||
|
|
||||||
mod.featured.dialog.title = Mod Browser (unfertig)
|
mod.featured.dialog.title = Mod Browser
|
||||||
mods.browser.selected = Ausgewählter Mod
|
mods.browser.selected = Ausgewählter Mod
|
||||||
mods.browser.add = Installieren
|
mods.browser.add = Installieren
|
||||||
mods.github.open = Ansehen
|
mods.browser.reinstall = Neu Installieren
|
||||||
|
mods.github.open = Github
|
||||||
|
mods.browser.sortdate = Nach neusten sortieren
|
||||||
|
mods.browser.sortstars = Nach Sternen sortieren
|
||||||
|
|
||||||
schematic = Entwurf
|
schematic = Entwurf
|
||||||
schematic.add = Entwurf speichern...
|
schematic.add = Entwurf speichern...
|
||||||
@@ -116,8 +119,10 @@ mods.none = [lightgray]Keine Mods gefunden!
|
|||||||
mods.guide = Modding-Anleitung
|
mods.guide = Modding-Anleitung
|
||||||
mods.report = Problem melden
|
mods.report = Problem melden
|
||||||
mods.openfolder = Mod-Verzeichnis öffnen
|
mods.openfolder = Mod-Verzeichnis öffnen
|
||||||
|
mods.viewcontent = Inhalt ansehen
|
||||||
mods.reload = Neu laden
|
mods.reload = Neu laden
|
||||||
mods.reloadexit = Das Spiel wird jetzt beendet, um die Mod-Änderungen anzuwenden.
|
mods.reloadexit = Das Spiel wird jetzt beendet, um die Mod-Änderungen anzuwenden.
|
||||||
|
mod.installed = [[Installiert]
|
||||||
mod.display = [gray]Mod:[orange] {0}
|
mod.display = [gray]Mod:[orange] {0}
|
||||||
mod.enabled = [lightgray]Aktiviert
|
mod.enabled = [lightgray]Aktiviert
|
||||||
mod.disabled = [scarlet]Deaktiviert
|
mod.disabled = [scarlet]Deaktiviert
|
||||||
@@ -287,6 +292,7 @@ cancel = Abbruch
|
|||||||
openlink = Link öffnen
|
openlink = Link öffnen
|
||||||
copylink = Link kopieren
|
copylink = Link kopieren
|
||||||
back = Zurück
|
back = Zurück
|
||||||
|
max = Max
|
||||||
crash.export = Crash-Logs exportieren
|
crash.export = Crash-Logs exportieren
|
||||||
crash.none = Keine Crash-Logs gefunden.
|
crash.none = Keine Crash-Logs gefunden.
|
||||||
crash.exported = Crash-Logs wurden erfolgreich exportiert.
|
crash.exported = Crash-Logs wurden erfolgreich exportiert.
|
||||||
@@ -361,7 +367,6 @@ editor.center = Zur Mitte
|
|||||||
workshop = Workshop
|
workshop = Workshop
|
||||||
waves.title = Wellen
|
waves.title = Wellen
|
||||||
waves.remove = Entfernen
|
waves.remove = Entfernen
|
||||||
waves.never = <nie>
|
|
||||||
waves.every = alle
|
waves.every = alle
|
||||||
waves.waves = Welle(n)
|
waves.waves = Welle(n)
|
||||||
waves.perspawn = pro Spawn
|
waves.perspawn = pro Spawn
|
||||||
@@ -390,7 +395,7 @@ editor.removeunit = Bereich entfernen
|
|||||||
editor.teams = Teams
|
editor.teams = Teams
|
||||||
editor.errorload = Fehler beim Laden der Datei:\n[accent]{0}
|
editor.errorload = Fehler beim Laden der Datei:\n[accent]{0}
|
||||||
editor.errorsave = Fehler beim Speichern der Datei:\n[accent]{0}
|
editor.errorsave = Fehler beim Speichern der Datei:\n[accent]{0}
|
||||||
editor.errorimage = Das ist ein Bild, keine Karte. Wechsle nicht den Dateityp und erwarte, dass es funktioniert.\n\nWenn du eine 'v3.5/build 40'-Karte importieren möchtest, benutze den 'Importiere Terrainbild'-Knopf im Editor.
|
editor.errorimage = Das ist ein Bild, keine Karte.
|
||||||
editor.errorlegacy = Diese Karte ist zu alt und benutzt ein veraltetes Kartenformat, das nicht mehr unterstützt wird.
|
editor.errorlegacy = Diese Karte ist zu alt und benutzt ein veraltetes Kartenformat, das nicht mehr unterstützt wird.
|
||||||
editor.errornot = Dies ist keine Kartendatei.
|
editor.errornot = Dies ist keine Kartendatei.
|
||||||
editor.errorheader = Diese Karte ist entweder nicht gültig oder beschädigt.
|
editor.errorheader = Diese Karte ist entweder nicht gültig oder beschädigt.
|
||||||
@@ -693,6 +698,7 @@ stat.lightningchance = Blitzwahrscheinlichkeit
|
|||||||
stat.lightningdamage = Blitzschaden
|
stat.lightningdamage = Blitzschaden
|
||||||
stat.flammability = Brennbarkeit
|
stat.flammability = Brennbarkeit
|
||||||
stat.radioactivity = Radioaktivität
|
stat.radioactivity = Radioaktivität
|
||||||
|
stat.charge = Ladung
|
||||||
stat.heatcapacity = Hitzekapazität
|
stat.heatcapacity = Hitzekapazität
|
||||||
stat.viscosity = Viskosität
|
stat.viscosity = Viskosität
|
||||||
stat.temperature = Temperatur
|
stat.temperature = Temperatur
|
||||||
@@ -720,6 +726,7 @@ bar.corereq = Kern-Basis erforderlich
|
|||||||
bar.drillspeed = Bohrgeschwindigkeit: {0}/s
|
bar.drillspeed = Bohrgeschwindigkeit: {0}/s
|
||||||
bar.pumpspeed = Pumpengeschwindigkeit: {0}/s
|
bar.pumpspeed = Pumpengeschwindigkeit: {0}/s
|
||||||
bar.efficiency = Effizienz: {0}%
|
bar.efficiency = Effizienz: {0}%
|
||||||
|
bar.boost = Beschleunigung: {0}%
|
||||||
bar.powerbalance = Strom: {0}/s
|
bar.powerbalance = Strom: {0}/s
|
||||||
bar.powerstored = Gespeichert: {0}/{1}
|
bar.powerstored = Gespeichert: {0}/{1}
|
||||||
bar.poweramount = Strom: {0}
|
bar.poweramount = Strom: {0}
|
||||||
@@ -935,6 +942,7 @@ mode.custom = Angepasste Regeln
|
|||||||
|
|
||||||
rules.infiniteresources = Unbegrenzte Ressourcen
|
rules.infiniteresources = Unbegrenzte Ressourcen
|
||||||
rules.reactorexplosions = Reaktor-Explosionen
|
rules.reactorexplosions = Reaktor-Explosionen
|
||||||
|
rules.coreincinerates = Kern verbrennt überflüssige Materialien
|
||||||
rules.schematic = Entwürfe erlaubt
|
rules.schematic = Entwürfe erlaubt
|
||||||
rules.wavetimer = Wellen-Timer
|
rules.wavetimer = Wellen-Timer
|
||||||
rules.waves = Wellen
|
rules.waves = Wellen
|
||||||
@@ -1381,8 +1389,8 @@ block.inverted-sorter.description = Wie ein normaler Sortierer, aber gibt das au
|
|||||||
block.router.description = Verteilt Materialien auf bis zu drei Richtungen.
|
block.router.description = Verteilt Materialien auf bis zu drei Richtungen.
|
||||||
block.router.details = Ein nötiges Übel. Es ist nicht empfehlenswert, ihn neben Fabriken zu setzen, da er sich dort verstopfen kann.
|
block.router.details = Ein nötiges Übel. Es ist nicht empfehlenswert, ihn neben Fabriken zu setzen, da er sich dort verstopfen kann.
|
||||||
block.distributor.description = Verteilt Materialien auf bis zu sieben Richtungen.
|
block.distributor.description = Verteilt Materialien auf bis zu sieben Richtungen.
|
||||||
block.overflow-gate.description = Gibt Materialien nur zu den Seiten heraus, wenn der fordere Ausgang blockiert ist. Kann nicht neben anderen Überlauf- oder Unterlauftoren verwendet werden.
|
block.overflow-gate.description = Gibt Materialien nur zu den Seiten heraus, wenn der fordere Ausgang blockiert ist.
|
||||||
block.underflow-gate.description = Das Gegenteil eines Überlauftors. Gibt Materialien nur nach vorne heraus, wenn die Seiten blockiert sind. Kann nicht neben anderen Überlauf- oder Unterlauftoren verwendet werden.
|
block.underflow-gate.description = Das Gegenteil eines Überlauftors. Gibt Materialien nur nach vorne heraus, wenn die Seiten blockiert sind.
|
||||||
block.mass-driver.description = Ein Transportblock mit sehr hoher Reichweite. Sammelt mehrere Materialien und schießt sie zu einem verbundenen Massenbeschleuniger.
|
block.mass-driver.description = Ein Transportblock mit sehr hoher Reichweite. Sammelt mehrere Materialien und schießt sie zu einem verbundenen Massenbeschleuniger.
|
||||||
block.mechanical-pump.description = Eine Pumpe, die keinen Strom benötigt.
|
block.mechanical-pump.description = Eine Pumpe, die keinen Strom benötigt.
|
||||||
block.rotary-pump.description = Eine Pumpe, die Strom verbraucht.
|
block.rotary-pump.description = Eine Pumpe, die Strom verbraucht.
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ pausebuilding = Használd a(z) [accent][[{0}][] gombot, hogy megállítsd az ép
|
|||||||
resumebuilding = Használd a(z) [scarlet][[{0}][] gombot, hogy folytasd az építkezést.
|
resumebuilding = Használd a(z) [scarlet][[{0}][] gombot, hogy folytasd az építkezést.
|
||||||
showui = A kezelőfelület elrejtve.\nNyomja meg a(z) [accent][[{0}][] gombot a megjelenítéséhez.
|
showui = A kezelőfelület elrejtve.\nNyomja meg a(z) [accent][[{0}][] gombot a megjelenítéséhez.
|
||||||
wave = [accent]{0}. Hullám
|
wave = [accent]{0}. Hullám
|
||||||
wave.cap = [accent]{0}/{1}. Hullám
|
wave.cap = [accent]{0}/{1} Hullám
|
||||||
wave.waiting = [lightgray]Következő hullám {0}
|
wave.waiting = [lightgray]Következő hullám {0}
|
||||||
wave.waveInProgress = [lightgray]Hullám folyamatban
|
wave.waveInProgress = [lightgray]Hullám folyamatban
|
||||||
waiting = [lightgray]Várakozás...
|
waiting = [lightgray]Várakozás...
|
||||||
@@ -316,7 +316,7 @@ waiting.players = Várakozás a játékosokra...
|
|||||||
wave.enemies = [lightgray]Fennmaradó ellenségek: {0}
|
wave.enemies = [lightgray]Fennmaradó ellenségek: {0}
|
||||||
wave.enemycores = [accent]{0}[lightgray] Ellenséges magok
|
wave.enemycores = [accent]{0}[lightgray] Ellenséges magok
|
||||||
wave.enemycore = [accent]{0}[lightgray] Ellenséges mag
|
wave.enemycore = [accent]{0}[lightgray] Ellenséges mag
|
||||||
wave.enemy = [lightgray]{0} Magmaradt ellenség
|
wave.enemy = [lightgray]{0} Megmaradt ellenség
|
||||||
wave.guardianwarn = Az őrző [accent]{0}[] hullám múlva érkezik.
|
wave.guardianwarn = Az őrző [accent]{0}[] hullám múlva érkezik.
|
||||||
wave.guardianwarn.one = Az őrző [accent]{0}[] hullám múlva érkezik.
|
wave.guardianwarn.one = Az őrző [accent]{0}[] hullám múlva érkezik.
|
||||||
loadimage = Fénykép betöltése
|
loadimage = Fénykép betöltése
|
||||||
|
|||||||
@@ -41,11 +41,12 @@ be.ignore = Abaikan
|
|||||||
be.noupdates = Tidak ada pembaruan yang ditemukan.
|
be.noupdates = Tidak ada pembaruan yang ditemukan.
|
||||||
be.check = Cek versi baru
|
be.check = Cek versi baru
|
||||||
|
|
||||||
mod.featured.title = Browser mod
|
|
||||||
mod.featured.dialog.title = Browser Mod
|
mod.featured.dialog.title = Browser Mod
|
||||||
mods.browser.selected = Mod yang Dipilih
|
mods.browser.selected = Mod yang Dipilih
|
||||||
mods.browser.add = Unduh Mod
|
mods.browser.add = Unduh Mod
|
||||||
mods.github.open = Buka di GitHub
|
mods.github.open = Buka di GitHub
|
||||||
|
mods.browser.sortdate = Urut berdasarkan waktu
|
||||||
|
mods.browser.sortstars = Urut berdasarkan bintang
|
||||||
|
|
||||||
schematic = Skema
|
schematic = Skema
|
||||||
schematic.add = Menyimpan skema...
|
schematic.add = Menyimpan skema...
|
||||||
@@ -90,6 +91,7 @@ joingame = Bermain Bersama
|
|||||||
customgame = Permainan Modifikasi
|
customgame = Permainan Modifikasi
|
||||||
newgame = Permainan Baru
|
newgame = Permainan Baru
|
||||||
none = <kosong>
|
none = <kosong>
|
||||||
|
none.found = [lightgray]<tidak ditemukan>
|
||||||
minimap = Peta Kecil
|
minimap = Peta Kecil
|
||||||
position = Posisi
|
position = Posisi
|
||||||
close = Tutup
|
close = Tutup
|
||||||
@@ -1383,7 +1385,7 @@ block.inverted-sorter.description = Sama seperti penyortir, melainkan mengeluark
|
|||||||
block.router.description = Menerima bahan dari satu arah dan mengeluarkannya ke 3 arah yang sama. Bisa juga menyimpan sejumlah bahan. Berguna untuk memisahkan bahan dari satu sumber ke target yang banyak.
|
block.router.description = Menerima bahan dari satu arah dan mengeluarkannya ke 3 arah yang sama. Bisa juga menyimpan sejumlah bahan. Berguna untuk memisahkan bahan dari satu sumber ke target yang banyak.
|
||||||
block.router.details = Bisa sangat menggangu. Jangan meletakannya disamping input produksi, karena bisa tersumbat oleh output.
|
block.router.details = Bisa sangat menggangu. Jangan meletakannya disamping input produksi, karena bisa tersumbat oleh output.
|
||||||
block.distributor.description = Pemisah canggih yang memisah item ke 7 arah berbeda bersamaan.
|
block.distributor.description = Pemisah canggih yang memisah item ke 7 arah berbeda bersamaan.
|
||||||
block.overflow-gate.description = Kombinasi antara pemisah dan penyortir yang hanya mengeluarkan item ke kiri dan/atau ke kanan jika bagian depan tertutup.
|
block.overflow-gate.description = Hanya mengeluarkan item ke kiri dan/atau ke kanan jika bagian depan tertutup.
|
||||||
block.underflow-gate.description = Kebalikan dari gerbang luap. Mengeluarkan ke depan jika kanan dan kiri tertutup.
|
block.underflow-gate.description = Kebalikan dari gerbang luap. Mengeluarkan ke depan jika kanan dan kiri tertutup.
|
||||||
block.mass-driver.description = Blok item transportasi tercanggih. Membawa beberapa item dan menembaknya ke penggerak massal lainnya dari arah yang jauh.
|
block.mass-driver.description = Blok item transportasi tercanggih. Membawa beberapa item dan menembaknya ke penggerak massal lainnya dari arah yang jauh.
|
||||||
block.mechanical-pump.description = Pompa murah dengan pengeluaran yang pelan, tetapi tidak mengkonsumsi tenaga.
|
block.mechanical-pump.description = Pompa murah dengan pengeluaran yang pelan, tetapi tidak mengkonsumsi tenaga.
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ mod.featured.dialog.title = 모드 탐색 (WIP)
|
|||||||
mods.browser.selected = 선택된 모드
|
mods.browser.selected = 선택된 모드
|
||||||
mods.browser.add = 모드 설치
|
mods.browser.add = 모드 설치
|
||||||
mods.github.open = 깃허브 사이트 열기
|
mods.github.open = 깃허브 사이트 열기
|
||||||
|
mods.browser.sortdate = 최근 업데이트
|
||||||
|
mods.browser.sortstars = 추천(스타) 수
|
||||||
|
|
||||||
schematic = 설계도
|
schematic = 설계도
|
||||||
schematic.add = 설계도 저장하기
|
schematic.add = 설계도 저장하기
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ link.trello.description = Oficjalna tablica Trello z planowanym funkcjami
|
|||||||
link.itch.io.description = Strona itch.io z oficjanymi wersjami do pobrania
|
link.itch.io.description = Strona itch.io z oficjanymi wersjami do pobrania
|
||||||
link.google-play.description = Strona w sklepie Google Play
|
link.google-play.description = Strona w sklepie Google Play
|
||||||
link.f-droid.description = Wykaz Katalogu F-Droid
|
link.f-droid.description = Wykaz Katalogu F-Droid
|
||||||
link.wiki.description = Oficjana Wiki Mindustry
|
link.wiki.description = Oficjalna Wiki Mindustry
|
||||||
link.suggestions.description = Zaproponuj nowe funkcje
|
link.suggestions.description = Zaproponuj nowe funkcje
|
||||||
link.bug.description = Znalazłeś błąd? Zgłoś go tutaj
|
link.bug.description = Znalazłeś błąd? Zgłoś go tutaj
|
||||||
linkfail = Nie udało się otworzyć linku!\nURL został skopiowany.
|
linkfail = Nie udało się otworzyć linku!\nURL został skopiowany.
|
||||||
@@ -1277,7 +1277,7 @@ hint.placeTurret = Postaw \uf861 [accent]Działka[] by bronić się przed wrogam
|
|||||||
hint.breaking = Użyj [accent]Prawego przycisku myszy[] i przeciągnij by zniszczyć bloki.
|
hint.breaking = Użyj [accent]Prawego przycisku myszy[] i przeciągnij by zniszczyć bloki.
|
||||||
hint.breaking.mobile = Aktywuj \ue817 [accent]ikonę młota[] w dolnym prawym rogu by zniszczyć bloki.\n\nPrzytrymaj swój palec i przeciągij by wybrać wiele bloków do zniszczenia.
|
hint.breaking.mobile = Aktywuj \ue817 [accent]ikonę młota[] w dolnym prawym rogu by zniszczyć bloki.\n\nPrzytrymaj swój palec i przeciągij by wybrać wiele bloków do zniszczenia.
|
||||||
hint.research = Klikij przycisk \ue875 [accent]Badań[] by odkrwyać nowe technologie.
|
hint.research = Klikij przycisk \ue875 [accent]Badań[] by odkrwyać nowe technologie.
|
||||||
hint.research.mobile = Użyj przycisku \ue875 [accent]Badań[] w \ue88c [accent]Menu[] by odkrwyać nowe technologie.
|
hint.research.mobile = Użyj przycisku \ue875 [accent]Badań[] w \ue88c [accent]Menu[] by odkrywać nowe technologie.
|
||||||
hint.unitControl = Przytrzymaj [accent][[Lewy CTRL][] i [accent]kliknij[] by kontrolować sojusznicze jednostki i działka.
|
hint.unitControl = Przytrzymaj [accent][[Lewy CTRL][] i [accent]kliknij[] by kontrolować sojusznicze jednostki i działka.
|
||||||
hint.unitControl.mobile = [accent][Kliknij dwukrotnie[] by kontrolować sojusznicze jednostki i działka.
|
hint.unitControl.mobile = [accent][Kliknij dwukrotnie[] by kontrolować sojusznicze jednostki i działka.
|
||||||
hint.launch = Gdy zebrałeś wystarczająco materiałów możesz [accent]Wystrzelić[] wybierając \ue827 [accent]Mapę[] w dolnym prawym rogu.
|
hint.launch = Gdy zebrałeś wystarczająco materiałów możesz [accent]Wystrzelić[] wybierając \ue827 [accent]Mapę[] w dolnym prawym rogu.
|
||||||
@@ -1290,10 +1290,10 @@ hint.command = Kliknij [accent][[G][] by ukształtować formacje z pobliskich je
|
|||||||
hint.command.mobile = [accent][[Podwójne kliknięcie][] kształtuje formacje z pobliskich jednostek.
|
hint.command.mobile = [accent][[Podwójne kliknięcie][] kształtuje formacje z pobliskich jednostek.
|
||||||
hint.payloadPickup = Kliknij [accent][[[] by podnieść małe bloki lub jednostki.
|
hint.payloadPickup = Kliknij [accent][[[] by podnieść małe bloki lub jednostki.
|
||||||
hint.payloadPickup.mobile = [accent]Kliknij i przytrzymaj[] mały blok by go podnieść.
|
hint.payloadPickup.mobile = [accent]Kliknij i przytrzymaj[] mały blok by go podnieść.
|
||||||
hint.payloadDrop = Kliknij [accent]][] by opuścić podniesoiny towar.
|
hint.payloadDrop = Kliknij [accent]][] by opuścić podniesiony towar.
|
||||||
hint.payloadDrop.mobile = [accent]Kliknij i przytrzymaj[] w puste miejsce by opuścić podniesoiny towar.
|
hint.payloadDrop.mobile = [accent]Kliknij i przytrzymaj[] w puste miejsce by opuścić podniesiony towar.
|
||||||
hint.waveFire = [accent]Strumień[] wypełniony wodą będzie gasić pobiskie pożary.
|
hint.waveFire = [accent]Strumień[] wypełniony wodą będzie gasić pobiskie pożary.
|
||||||
hint.generator = \uf879 [accent]Generatory Spalinowe[] spalają węgiel i przekuzują moc do pobliskich bloków.\n\nMożesz powiększyć odległość transmitowanej mocy używająć \uf87f [accent]Węzły Prądu[].
|
hint.generator = \uf879 [accent]Generatory Spalinowe[] spalają węgiel i przekazują moc do pobliskich bloków.\n\nMożesz powiększyć odległość transmitowanej mocy używająć \uf87f [accent]Węzły Prądu[].
|
||||||
hint.guardian = Jednostki [accent]Strażnicze[] są uzbrojone. Słaba amunicja - taka jak [accent]Miedź[] oraz [accent]Ołów[] [scarlet]nie jest efektywna[].\n\nUżyj lepszych działek takich jak \uf835 [accent]Naładowane Grafitem[] \uf861Duo/\uf859Salwa by pozbyć się strażników.
|
hint.guardian = Jednostki [accent]Strażnicze[] są uzbrojone. Słaba amunicja - taka jak [accent]Miedź[] oraz [accent]Ołów[] [scarlet]nie jest efektywna[].\n\nUżyj lepszych działek takich jak \uf835 [accent]Naładowane Grafitem[] \uf861Duo/\uf859Salwa by pozbyć się strażników.
|
||||||
hint.coreUpgrade = Rdzenie mogą być ulepszone poprzez [accent]płożenie na nich rdzeń wyższego poziomu[].\n\nPołóż rdzeń [accent]Fundacji[] na rdzeń:[accent]Odłamek[] core. Żadna przeszkoda ani blok nie może stać na miejscu rdzenia.
|
hint.coreUpgrade = Rdzenie mogą być ulepszone poprzez [accent]płożenie na nich rdzeń wyższego poziomu[].\n\nPołóż rdzeń [accent]Fundacji[] na rdzeń:[accent]Odłamek[] core. Żadna przeszkoda ani blok nie może stać na miejscu rdzenia.
|
||||||
hint.presetLaunch = Szare [accent]sektory[], takie jak [accent]Zamrożony Las[], to sektory do których możesz dotrzeć z każdego miejsca. Nie wymagają podbicia pobliskiego terenu.\n\n[accent]Ponumerowane sektory[], takie jak ten, [accent]są dodatkowe[].
|
hint.presetLaunch = Szare [accent]sektory[], takie jak [accent]Zamrożony Las[], to sektory do których możesz dotrzeć z każdego miejsca. Nie wymagają podbicia pobliskiego terenu.\n\n[accent]Ponumerowane sektory[], takie jak ten, [accent]są dodatkowe[].
|
||||||
@@ -1357,8 +1357,8 @@ block.copper-wall.description = Tani blok obronny.\nPrzydatny do ochrony rdzenia
|
|||||||
block.copper-wall-large.description = Tani blok obronny.\nPrzydatny do ochrony rdzenia i wieżyczek w pierwszych kilku falach.\nObejmuje wiele kratek.
|
block.copper-wall-large.description = Tani blok obronny.\nPrzydatny do ochrony rdzenia i wieżyczek w pierwszych kilku falach.\nObejmuje wiele kratek.
|
||||||
block.titanium-wall.description = Umiarkowanie silny blok obronny.\nZapewnia umiarkowaną ochronę przed wrogami.
|
block.titanium-wall.description = Umiarkowanie silny blok obronny.\nZapewnia umiarkowaną ochronę przed wrogami.
|
||||||
block.titanium-wall-large.description = Umiarkowanie silny blok obronny.\nZapewnia umiarkowaną ochronę przed wrogami.\nObejmuje wiele kratek.
|
block.titanium-wall-large.description = Umiarkowanie silny blok obronny.\nZapewnia umiarkowaną ochronę przed wrogami.\nObejmuje wiele kratek.
|
||||||
block.plastanium-wall.description = Specjajny typ ściany, który pochłania łuki elektryczne oraz blokuje automatyczne łączenie węzłów.
|
block.plastanium-wall.description = Specjalny typ ściany, który pochłania łuki elektryczne oraz blokuje automatyczne łączenie węzłów.
|
||||||
block.plastanium-wall-large.description = Specjajny typ ściany, który pochłania łuki elektryczne oraz blokuje automatyczne łączenie węzłów.\nObejmuje wiele kratek.
|
block.plastanium-wall-large.description = Specjalny typ ściany, który pochłania łuki elektryczne oraz blokuje automatyczne łączenie węzłów.\nObejmuje wiele kratek.
|
||||||
block.thorium-wall.description = Silny blok obronny.\nDobra ochrona przed wrogami.
|
block.thorium-wall.description = Silny blok obronny.\nDobra ochrona przed wrogami.
|
||||||
block.thorium-wall-large.description = Silny blok obronny.\nDobra ochrona przed wrogami.\nObejmuje wiele kratek.
|
block.thorium-wall-large.description = Silny blok obronny.\nDobra ochrona przed wrogami.\nObejmuje wiele kratek.
|
||||||
block.phase-wall.description = Ściana pokryta specjalną mieszanką opartą o Włókna Fazowe, która odbija większość pocisków.
|
block.phase-wall.description = Ściana pokryta specjalną mieszanką opartą o Włókna Fazowe, która odbija większość pocisków.
|
||||||
|
|||||||
@@ -41,11 +41,13 @@ be.ignore = Ignoră
|
|||||||
be.noupdates = Niciun update disponibil.
|
be.noupdates = Niciun update disponibil.
|
||||||
be.check = Verifică updateurile
|
be.check = Verifică updateurile
|
||||||
|
|
||||||
mod.featured.title = Mod browser
|
mods.browser = Browser de Moduri
|
||||||
mod.featured.dialog.title = Mod Browser (Neterminat)
|
|
||||||
mods.browser.selected = Mod selectat
|
mods.browser.selected = Mod selectat
|
||||||
mods.browser.add = Instalează
|
mods.browser.add = Instalează
|
||||||
mods.github.open = Vezi
|
mods.browser.reinstall = Reinstalează
|
||||||
|
mods.github.open = Github
|
||||||
|
mods.browser.sortdate = Cele mai recente
|
||||||
|
mods.browser.sortstars = Cele mai multe stele
|
||||||
|
|
||||||
schematic = Schemă
|
schematic = Schemă
|
||||||
schematic.add = Salvează Schema...
|
schematic.add = Salvează Schema...
|
||||||
@@ -117,8 +119,10 @@ mods.none = [lightgray]Nu s-au găsit moduri!
|
|||||||
mods.guide = Ghid de Modding
|
mods.guide = Ghid de Modding
|
||||||
mods.report = Raportează Bug
|
mods.report = Raportează Bug
|
||||||
mods.openfolder = Deschide Folder
|
mods.openfolder = Deschide Folder
|
||||||
|
mods.viewcontent = Vezi Conținut
|
||||||
mods.reload = Reîncarcă
|
mods.reload = Reîncarcă
|
||||||
mods.reloadexit = Jocul se va opri ca să reîncarce modurile.
|
mods.reloadexit = Jocul se va opri ca să reîncarce modurile.
|
||||||
|
mod.installed = [[Instalat]
|
||||||
mod.display = [gray]Mod:[orange] {0}
|
mod.display = [gray]Mod:[orange] {0}
|
||||||
mod.enabled = [lightgray]Activat
|
mod.enabled = [lightgray]Activat
|
||||||
mod.disabled = [scarlet]Dezactivat
|
mod.disabled = [scarlet]Dezactivat
|
||||||
@@ -697,6 +701,7 @@ stat.radioactivity = Radioactivitate
|
|||||||
stat.heatcapacity = Capacitate de Căldură
|
stat.heatcapacity = Capacitate de Căldură
|
||||||
stat.viscosity = Vâscozitate
|
stat.viscosity = Vâscozitate
|
||||||
stat.temperature = Temperatură
|
stat.temperature = Temperatură
|
||||||
|
stat.charge = Sarcină Electrică
|
||||||
stat.speed = Viteză
|
stat.speed = Viteză
|
||||||
stat.buildspeed = Viteză Construcție
|
stat.buildspeed = Viteză Construcție
|
||||||
stat.minespeed = Viteză Minare
|
stat.minespeed = Viteză Minare
|
||||||
@@ -1384,8 +1389,8 @@ block.inverted-sorter.description = Similar sortatorului standard, dar materialu
|
|||||||
block.router.description = Distribuie materialele primite în alte 3 direcții în mod egal.
|
block.router.description = Distribuie materialele primite în alte 3 direcții în mod egal.
|
||||||
block.router.details = Un rău necesar. Nu folosi niciodată pt a introduce materiale în blocuri, căci vor fi blocate de produșii blocurilor.
|
block.router.details = Un rău necesar. Nu folosi niciodată pt a introduce materiale în blocuri, căci vor fi blocate de produșii blocurilor.
|
||||||
block.distributor.description = Distribuie materialele primite în alte 7 direcții în mod egal.
|
block.distributor.description = Distribuie materialele primite în alte 7 direcții în mod egal.
|
||||||
block.overflow-gate.description = Transportă materialele doar la stânga și dreapta dacă drumul din față este blocat. Nu poate fi folosită lângă alte porți.
|
block.overflow-gate.description = Transportă materialele doar la stânga și dreapta dacă drumul din față este blocat.
|
||||||
block.underflow-gate.description = Opusul porții de revărsare. Transportă materialele în față dacă benzile din stânga și dreapta sunt blocate. Nu poate fi folosită lângă alte porți.
|
block.underflow-gate.description = Opusul porții de revărsare. Transportă materialele în față dacă benzile din stânga și dreapta sunt blocate.
|
||||||
block.mass-driver.description = Dispozitiv folosit pt transportul materialelor pe distanțe mari. Adună mai multe materiale și apoi le lansează până la un alt distributor în masă pe o rază mare.
|
block.mass-driver.description = Dispozitiv folosit pt transportul materialelor pe distanțe mari. Adună mai multe materiale și apoi le lansează până la un alt distributor în masă pe o rază mare.
|
||||||
block.mechanical-pump.description = Pompează lichide din mediul înconjurător. Nu necesită electricitate.
|
block.mechanical-pump.description = Pompează lichide din mediul înconjurător. Nu necesită electricitate.
|
||||||
block.rotary-pump.description = Pompează lichide din mediul înconjurător. Necesită electricitate.
|
block.rotary-pump.description = Pompează lichide din mediul înconjurător. Necesită electricitate.
|
||||||
|
|||||||
@@ -41,10 +41,13 @@ be.ignore = Игнорировать
|
|||||||
be.noupdates = Обновления не найдены.
|
be.noupdates = Обновления не найдены.
|
||||||
be.check = Проверить обновления
|
be.check = Проверить обновления
|
||||||
|
|
||||||
mod.featured.dialog.title = Браузер модификаций
|
mods.browser = Браузер\nмодификаций
|
||||||
mods.browser.selected = Выбранный мод
|
mods.browser.selected = Выбранный мод
|
||||||
mods.browser.add = Скачать
|
mods.browser.add = Скачать
|
||||||
mods.github.open = Открыть
|
mods.browser.reinstall = Переустановить
|
||||||
|
mods.github.open = Сайт
|
||||||
|
mods.browser.sortdate = Сортировка по дате
|
||||||
|
mods.browser.sortstars = Сортировка по звёздам
|
||||||
|
|
||||||
schematic = Схема
|
schematic = Схема
|
||||||
schematic.add = Сохранить схему…
|
schematic.add = Сохранить схему…
|
||||||
@@ -116,8 +119,10 @@ mods.none = [lightgray]Модификации не найдены!
|
|||||||
mods.guide = Руководство по модификациям
|
mods.guide = Руководство по модификациям
|
||||||
mods.report = Доложить об ошибке
|
mods.report = Доложить об ошибке
|
||||||
mods.openfolder = Открыть папку с модификациями
|
mods.openfolder = Открыть папку с модификациями
|
||||||
|
mods.viewcontent = Просмотреть содержимое
|
||||||
mods.reload = Перезагрузить
|
mods.reload = Перезагрузить
|
||||||
mods.reloadexit = Игра будет закрыта для перезагрузки модификаций.
|
mods.reloadexit = Игра будет закрыта для перезагрузки модификаций.
|
||||||
|
mod.installed = [[Установлено]
|
||||||
mod.display = [gray]Модификация:[orange] {0}
|
mod.display = [gray]Модификация:[orange] {0}
|
||||||
mod.enabled = [lightgray]Включён
|
mod.enabled = [lightgray]Включён
|
||||||
mod.disabled = [scarlet]Выключен
|
mod.disabled = [scarlet]Выключен
|
||||||
@@ -327,9 +332,9 @@ custom = Пользовательская
|
|||||||
builtin = Встроенная
|
builtin = Встроенная
|
||||||
map.delete.confirm = Вы действительно хотите удалить эту карту? Это действие не может быть отменено!
|
map.delete.confirm = Вы действительно хотите удалить эту карту? Это действие не может быть отменено!
|
||||||
map.random = [accent]Случайная карта
|
map.random = [accent]Случайная карта
|
||||||
map.nospawn = Эта карта не имеет ни одного ядра, в котором игрок может появиться! Добавьте[accent] оранжевое[] ядро на эту карту в редакторе.
|
map.nospawn = Эта карта не имеет ни одного ядра, в котором игрок может появиться! Добавьте [accent]оранжевое[] ядро на эту карту в редакторе.
|
||||||
map.nospawn.pvp = У этой карты нет вражеских ядер, в которых игрок может появиться! Добавьте[scarlet] не оранжевое[] ядро на эту карту в редакторе.
|
map.nospawn.pvp = У этой карты нет вражеских ядер, в которых игрок может появиться! Добавьте [scarlet]не оранжевое[] ядро на эту карту в редакторе.
|
||||||
map.nospawn.attack = У этой карты нет вражеских ядер для атаки игроком! Добавьте[scarlet] красное[] ядро на эту карту в редакторе.
|
map.nospawn.attack = У этой карты нет вражеских ядер для атаки игроком! Добавьте [scarlet]красное[] ядро на эту карту в редакторе.
|
||||||
map.invalid = Ошибка загрузки карты: повреждённый или недопустимый файл карты.
|
map.invalid = Ошибка загрузки карты: повреждённый или недопустимый файл карты.
|
||||||
workshop.update = Обновить содержимое
|
workshop.update = Обновить содержимое
|
||||||
workshop.error = Ошибка загрузки информации из Мастерской: {0}
|
workshop.error = Ошибка загрузки информации из Мастерской: {0}
|
||||||
@@ -693,6 +698,7 @@ stat.lightningchance = Шанс удара молнии
|
|||||||
stat.lightningdamage = Урон молнии
|
stat.lightningdamage = Урон молнии
|
||||||
stat.flammability = Воспламеняемость
|
stat.flammability = Воспламеняемость
|
||||||
stat.radioactivity = Радиоактивность
|
stat.radioactivity = Радиоактивность
|
||||||
|
stat.charge = Заряд
|
||||||
stat.heatcapacity = Теплоёмкость
|
stat.heatcapacity = Теплоёмкость
|
||||||
stat.viscosity = Вязкость
|
stat.viscosity = Вязкость
|
||||||
stat.temperature = Температура
|
stat.temperature = Температура
|
||||||
@@ -1383,8 +1389,8 @@ block.inverted-sorter.description = Работает так же, как и ст
|
|||||||
block.router.description = Равномерно распределяет входящие предметы по 3 выходящим направлениям.
|
block.router.description = Равномерно распределяет входящие предметы по 3 выходящим направлениям.
|
||||||
block.router.details = Необходимое зло. Не рекомендуется к использованию как блок ввода возле производственных зданий, т.к. может случиться затор выходным материалом.
|
block.router.details = Необходимое зло. Не рекомендуется к использованию как блок ввода возле производственных зданий, т.к. может случиться затор выходным материалом.
|
||||||
block.distributor.description = Равномерно распределяет входящие предметы по 7 выходящим направлениям.
|
block.distributor.description = Равномерно распределяет входящие предметы по 7 выходящим направлениям.
|
||||||
block.overflow-gate.description = Выводит предметы по бокам, только если передний путь заблокирован. Нельзя использовать вплотную к другим затворам или шлюзам.
|
block.overflow-gate.description = Выводит предметы по бокам, только если передний путь заблокирован.
|
||||||
block.underflow-gate.description = Противоположность избыточного затвора. Выводит предметы вперёд только в том случае, если боковые пути заблокированы. Нельзя использовать вплотную к другим шлюзам или затворам.
|
block.underflow-gate.description = Противоположность избыточного затвора. Выводит предметы вперёд только в том случае, если боковые пути заблокированы.
|
||||||
block.mass-driver.description = Постройка для дальней транспортировки предметов. Собирает несколько предметов и затем стреляет ими в другие катапульты.
|
block.mass-driver.description = Постройка для дальней транспортировки предметов. Собирает несколько предметов и затем стреляет ими в другие катапульты.
|
||||||
block.mechanical-pump.description = Перекачивает и выводит жидкости. Не требует энергию.
|
block.mechanical-pump.description = Перекачивает и выводит жидкости. Не требует энергию.
|
||||||
block.rotary-pump.description = Перекачивает и выводит жидкости. Требует энергию.
|
block.rotary-pump.description = Перекачивает и выводит жидкости. Требует энергию.
|
||||||
@@ -1497,10 +1503,10 @@ unit.poly.description = Автоматически восстанавливае
|
|||||||
unit.mega.description = Автоматически ремонтирует повреждённые постройки. Может переносить блоки и небольшие единицы.
|
unit.mega.description = Автоматически ремонтирует повреждённые постройки. Может переносить блоки и небольшие единицы.
|
||||||
unit.quad.description = Сбрасывает большие бомбы на наземные цели, восстанавливая союзные постройки и повреждая врагов. Может переносить единицы среднего размера.
|
unit.quad.description = Сбрасывает большие бомбы на наземные цели, восстанавливая союзные постройки и повреждая врагов. Может переносить единицы среднего размера.
|
||||||
unit.oct.description = Защищает союзников поблизости при помощи своего восстанавливающегося щита. Может переносить большинство наземных единиц.
|
unit.oct.description = Защищает союзников поблизости при помощи своего восстанавливающегося щита. Может переносить большинство наземных единиц.
|
||||||
unit.risso.description = Стреляет залпом ракет и пуль по всем врагам поблизости.
|
unit.risso.description = Стреляет залпами ракет и пуль по всем врагам поблизости.
|
||||||
unit.minke.description = Стреляет зажигательными снарядами и стандартными пулями по наземным целям.
|
unit.minke.description = Стреляет зажигательными снарядами и стандартными пулями по наземным целям.
|
||||||
unit.bryde.description = Стреляет дальнобойными артиллерийскими снарядами и ракетами по врагам.
|
unit.bryde.description = Стреляет дальнобойными артиллерийскими снарядами и ракетами по врагам.
|
||||||
unit.sei.description = Стреляет залпом ракет и бронебойных пуль по врагам.
|
unit.sei.description = Стреляет залпами ракет и бронебойных пуль по врагам.
|
||||||
unit.omura.description = Стреляет дальнобойным пробивающим снарядом из рельсотрона по врагам. Производит единицы «Вспышка».
|
unit.omura.description = Стреляет дальнобойным пробивающим снарядом из рельсотрона по врагам. Производит единицы «Вспышка».
|
||||||
unit.alpha.description = Защищает ядро «Осколок» от врагов. Основная строительная единица.
|
unit.alpha.description = Защищает ядро «Осколок» от врагов. Основная строительная единица.
|
||||||
unit.beta.description = Защищает ядро «Штаб» от врагов. Основная строительная единица.
|
unit.beta.description = Защищает ядро «Штаб» от врагов. Основная строительная единица.
|
||||||
|
|||||||
@@ -59,8 +59,10 @@ schematic.disabled = [scarlet]Схеми вимкнені[]\nВам не доз
|
|||||||
mod.featured.title = Переглядач модифікацій
|
mod.featured.title = Переглядач модифікацій
|
||||||
mod.featured.dialog.title = Переглядач модифікацій
|
mod.featured.dialog.title = Переглядач модифікацій
|
||||||
mods.browser.selected = Обрана модифікація
|
mods.browser.selected = Обрана модифікація
|
||||||
mods.browser.add = Установити модифікацію
|
mods.browser.add = Установити
|
||||||
mods.github.open = Відкрити в Github
|
mods.github.open = Відкрити
|
||||||
|
mods.browser.sortdate = Сортувати за давністю
|
||||||
|
mods.browser.sortstars = Сортувати за кількостю зірок
|
||||||
|
|
||||||
stats = Статистика
|
stats = Статистика
|
||||||
stat.wave = Хвиль відбито:[accent] {0}
|
stat.wave = Хвиль відбито:[accent] {0}
|
||||||
@@ -85,6 +87,7 @@ joingame = Мережева гра
|
|||||||
customgame = Користувацька гра
|
customgame = Користувацька гра
|
||||||
newgame = Нова гра
|
newgame = Нова гра
|
||||||
none = <нічого>
|
none = <нічого>
|
||||||
|
none.found = [lightgray]<нічого не знайдено>
|
||||||
minimap = Мінімапа
|
minimap = Мінімапа
|
||||||
position = Місцезнаходження
|
position = Місцезнаходження
|
||||||
close = Закрити
|
close = Закрити
|
||||||
@@ -278,6 +281,7 @@ cancel = Скасувати
|
|||||||
openlink = Перейти за посиланням
|
openlink = Перейти за посиланням
|
||||||
copylink = Скопіювати посилання
|
copylink = Скопіювати посилання
|
||||||
back = Назад
|
back = Назад
|
||||||
|
max = Макс.
|
||||||
crash.export = Експортувати аварійні звіти
|
crash.export = Експортувати аварійні звіти
|
||||||
crash.none = Аварійних звітів не знайдено
|
crash.none = Аварійних звітів не знайдено
|
||||||
crash.exported = Аварійні звіти експортовано
|
crash.exported = Аварійні звіти експортовано
|
||||||
@@ -351,7 +355,6 @@ editor.center = Центрувати
|
|||||||
workshop = Майстерня
|
workshop = Майстерня
|
||||||
waves.title = Хвилі
|
waves.title = Хвилі
|
||||||
waves.remove = Видалити
|
waves.remove = Видалити
|
||||||
waves.never = <ніколи>
|
|
||||||
waves.every = кожен
|
waves.every = кожен
|
||||||
waves.waves = хвиля(і)
|
waves.waves = хвиля(і)
|
||||||
waves.perspawn = за появу
|
waves.perspawn = за появу
|
||||||
@@ -377,7 +380,7 @@ editor.removeunit = Видалити бойову одиницю
|
|||||||
editor.teams = Команди
|
editor.teams = Команди
|
||||||
editor.errorload = Помилка завантаження зображення.
|
editor.errorload = Помилка завантаження зображення.
|
||||||
editor.errorsave = Помилка збереження зображення.
|
editor.errorsave = Помилка збереження зображення.
|
||||||
editor.errorimage = Це зображення, а не мапа.\n\nЯкщо ви хочете імпортувати застарілу мапу, то використовуйте кнопку «Імпортувати застарілу мапу» в редакторі.
|
editor.errorimage = Це зображення, а не мапа.
|
||||||
editor.errorlegacy = Ця мапа занадто стара і використовує попередній формат мапи, який більше не підтримується.
|
editor.errorlegacy = Ця мапа занадто стара і використовує попередній формат мапи, який більше не підтримується.
|
||||||
editor.errornot = Це не мапа.
|
editor.errornot = Це не мапа.
|
||||||
editor.errorheader = Цей файл мапи недійсний або пошкоджений.
|
editor.errorheader = Цей файл мапи недійсний або пошкоджений.
|
||||||
@@ -676,6 +679,7 @@ stat.commandlimit = Максимум у загоні
|
|||||||
stat.abilities = Здібності
|
stat.abilities = Здібності
|
||||||
stat.canboost = Можна прискорити
|
stat.canboost = Можна прискорити
|
||||||
stat.flying = Літає
|
stat.flying = Літає
|
||||||
|
stat.ammouse = Патронів використовує
|
||||||
ability.forcefield = Щитове поле
|
ability.forcefield = Щитове поле
|
||||||
ability.repairfield = Ремонтувальне поле
|
ability.repairfield = Ремонтувальне поле
|
||||||
ability.statusfield = Поле підсилення
|
ability.statusfield = Поле підсилення
|
||||||
@@ -688,6 +692,7 @@ bar.corereq = Необхідне основне ядро
|
|||||||
bar.drillspeed = Швидкість буріння: {0} за с.
|
bar.drillspeed = Швидкість буріння: {0} за с.
|
||||||
bar.pumpspeed = Швидкість викачування: {0} за с.
|
bar.pumpspeed = Швидкість викачування: {0} за с.
|
||||||
bar.efficiency = Ефективність: {0}%
|
bar.efficiency = Ефективність: {0}%
|
||||||
|
bar.boost = Підсилення: {0}%
|
||||||
bar.powerbalance = Енергія: {0} за с.
|
bar.powerbalance = Енергія: {0} за с.
|
||||||
bar.powerstored = Зберігає: {0}/{1}
|
bar.powerstored = Зберігає: {0}/{1}
|
||||||
bar.poweramount = Енергія: {0}
|
bar.poweramount = Енергія: {0}
|
||||||
@@ -696,7 +701,6 @@ bar.powerlines = З’єднань: {0}/{1}
|
|||||||
bar.items = Предмети: {0}
|
bar.items = Предмети: {0}
|
||||||
bar.capacity = Місткість: {0}
|
bar.capacity = Місткість: {0}
|
||||||
bar.unitcap = {0} {1}/{2}
|
bar.unitcap = {0} {1}/{2}
|
||||||
bar.limitreached = [scarlet] {0} / {1}[white] {2}\n[lightgray][[одиниця вимкнена]
|
|
||||||
bar.liquid = Рідина
|
bar.liquid = Рідина
|
||||||
bar.heat = Нагрівання
|
bar.heat = Нагрівання
|
||||||
bar.power = Енергія
|
bar.power = Енергія
|
||||||
@@ -711,6 +715,7 @@ bullet.sapping = [stat]виснажує
|
|||||||
bullet.homing = [stat]самонаведення
|
bullet.homing = [stat]самонаведення
|
||||||
bullet.shock = [stat]шок
|
bullet.shock = [stat]шок
|
||||||
bullet.frag = [stat]шкода по ділянці
|
bullet.frag = [stat]шкода по ділянці
|
||||||
|
bullet.buildingdamage = [stat]{0}%[lightgray] шкода по будівлям
|
||||||
bullet.knockback = [stat]{0}[lightgray] відкидання
|
bullet.knockback = [stat]{0}[lightgray] відкидання
|
||||||
bullet.pierce = [stat]{0}[lightgray]x пробиття
|
bullet.pierce = [stat]{0}[lightgray]x пробиття
|
||||||
bullet.infinitepierce = [stat]пробиття
|
bullet.infinitepierce = [stat]пробиття
|
||||||
@@ -738,6 +743,7 @@ unit.items = предм.
|
|||||||
unit.thousands = тис
|
unit.thousands = тис
|
||||||
unit.millions = млн
|
unit.millions = млн
|
||||||
unit.billions = млрд
|
unit.billions = млрд
|
||||||
|
unit.pershot = за постріл
|
||||||
category.purpose = Призначення
|
category.purpose = Призначення
|
||||||
category.general = Загальне
|
category.general = Загальне
|
||||||
category.power = Енергія
|
category.power = Енергія
|
||||||
@@ -806,6 +812,7 @@ setting.lasersopacity.name = Непрозорість лазерів енерг
|
|||||||
setting.bridgeopacity.name = Непрозорість мостів
|
setting.bridgeopacity.name = Непрозорість мостів
|
||||||
setting.playerchat.name = Показувати хмару чата над гравцями
|
setting.playerchat.name = Показувати хмару чата над гравцями
|
||||||
public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[accent]Будь-хто може приєднатися до вашої гри.\n[lightgray]Це можна змінити в Налаштування->Гра->Загальнодоступність гри.
|
public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[accent]Будь-хто може приєднатися до вашої гри.\n[lightgray]Це можна змінити в Налаштування->Гра->Загальнодоступність гри.
|
||||||
|
public.confirm.really = Якщо ви хочете грати з друзями, використовуйте [green]Запросити друзів[] замість [scarlet]Публічного серверу[]!\nВи справді хочете зробити свою гру [scarlet]публічною[]?
|
||||||
public.beta = Зауважте, що в бета-версії гри ви не можете робити публічні ігри.
|
public.beta = Зауважте, що в бета-версії гри ви не можете робити публічні ігри.
|
||||||
uiscale.reset = Масштаб користувацького інтерфейсу було змінено.\nНатисніть «Гаразд» для підтвердження цього масштабу.\n[scarlet]Повернення налаштувань і вихід через[accent] {0}[] секунд…
|
uiscale.reset = Масштаб користувацького інтерфейсу було змінено.\nНатисніть «Гаразд» для підтвердження цього масштабу.\n[scarlet]Повернення налаштувань і вихід через[accent] {0}[] секунд…
|
||||||
uiscale.cancel = Скасувати і вийти
|
uiscale.cancel = Скасувати і вийти
|
||||||
@@ -880,6 +887,7 @@ keybind.toggle_menus.name = Меню перемикання
|
|||||||
keybind.chat_history_prev.name = Попередня історія чату
|
keybind.chat_history_prev.name = Попередня історія чату
|
||||||
keybind.chat_history_next.name = Наступна історія чату
|
keybind.chat_history_next.name = Наступна історія чату
|
||||||
keybind.chat_scroll.name = Прокрутка чату
|
keybind.chat_scroll.name = Прокрутка чату
|
||||||
|
keybind.chat_mode.name = Змінити режим чату
|
||||||
keybind.drop_unit.name = Скинути бойову одиницю
|
keybind.drop_unit.name = Скинути бойову одиницю
|
||||||
keybind.zoom_minimap.name = Збільшити мінімапу
|
keybind.zoom_minimap.name = Збільшити мінімапу
|
||||||
mode.help.title = Опис режимів гри
|
mode.help.title = Опис режимів гри
|
||||||
@@ -895,6 +903,7 @@ mode.attack.description = Зруйнуйте ворожу базу. \n[gray]По
|
|||||||
mode.custom = Користувацькі правила
|
mode.custom = Користувацькі правила
|
||||||
rules.infiniteresources = Нескінченні ресурси
|
rules.infiniteresources = Нескінченні ресурси
|
||||||
rules.reactorexplosions = Вибухи реактора
|
rules.reactorexplosions = Вибухи реактора
|
||||||
|
rules.coreincinerates = Ядро спалює надлишкові предмети
|
||||||
rules.schematic = Використання схем дозволено
|
rules.schematic = Використання схем дозволено
|
||||||
rules.wavetimer = Таймер для хвиль
|
rules.wavetimer = Таймер для хвиль
|
||||||
rules.waves = Хвилі
|
rules.waves = Хвилі
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ mod.featured.dialog.title = 模組瀏覽器 (尚未完成)
|
|||||||
mods.browser.selected = 已選模組
|
mods.browser.selected = 已選模組
|
||||||
mods.browser.add = 安裝
|
mods.browser.add = 安裝
|
||||||
mods.github.open = 查看
|
mods.github.open = 查看
|
||||||
|
mods.browser.sortdate = 以最近篩選
|
||||||
|
mods.browser.sortstars = 以星數篩選
|
||||||
|
|
||||||
schematic = 藍圖
|
schematic = 藍圖
|
||||||
schematic.add = 儲存藍圖……
|
schematic.add = 儲存藍圖……
|
||||||
@@ -693,6 +695,7 @@ stat.lightningchance = 燃燒機率
|
|||||||
stat.lightningdamage = 燃燒傷害
|
stat.lightningdamage = 燃燒傷害
|
||||||
stat.flammability = 易燃性
|
stat.flammability = 易燃性
|
||||||
stat.radioactivity = 輻射性
|
stat.radioactivity = 輻射性
|
||||||
|
stat.charge = 蓄電力
|
||||||
stat.heatcapacity = 熱容量
|
stat.heatcapacity = 熱容量
|
||||||
stat.viscosity = 黏度
|
stat.viscosity = 黏度
|
||||||
stat.temperature = 溫度
|
stat.temperature = 溫度
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -50,8 +50,8 @@ public class Vars implements Loadable{
|
|||||||
public static final Charset charset = Charset.forName("UTF-8");
|
public static final Charset charset = Charset.forName("UTF-8");
|
||||||
/** main application name, capitalized */
|
/** main application name, capitalized */
|
||||||
public static final String appName = "Mindustry";
|
public static final String appName = "Mindustry";
|
||||||
/** URL for itch.io donations. */
|
/** Github API URL. */
|
||||||
public static final String donationURL = "https://anuke.itch.io/mindustry/purchase";
|
public static final String ghApi = "https://api.github.com";
|
||||||
/** URL for discord invite. */
|
/** URL for discord invite. */
|
||||||
public static final String discordURL = "https://discord.gg/mindustry";
|
public static final String discordURL = "https://discord.gg/mindustry";
|
||||||
/** URL for sending crash reports to */
|
/** URL for sending crash reports to */
|
||||||
@@ -345,7 +345,7 @@ public class Vars implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void loadSettings(){
|
public static void loadSettings(){
|
||||||
settings.setJson(JsonIO.json());
|
settings.setJson(JsonIO.json);
|
||||||
settings.setAppName(appName);
|
settings.setAppName(appName);
|
||||||
|
|
||||||
if(steam || (Version.modifier != null && Version.modifier.contains("steam"))){
|
if(steam || (Version.modifier != null && Version.modifier.contains("steam"))){
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ public class Pathfinder implements Runnable{
|
|||||||
private static final int updateFPS = 60;
|
private static final int updateFPS = 60;
|
||||||
private static final int updateInterval = 1000 / updateFPS;
|
private static final int updateInterval = 1000 / updateFPS;
|
||||||
private static final int impassable = -1;
|
private static final int impassable = -1;
|
||||||
private static final int fieldTimeout = 1000 * 60 * 2;
|
|
||||||
|
|
||||||
public static final int
|
public static final int
|
||||||
fieldCore = 0,
|
fieldCore = 0,
|
||||||
@@ -192,31 +191,6 @@ public class Pathfinder implements Runnable{
|
|||||||
//total update time no longer than maxUpdate
|
//total update time no longer than maxUpdate
|
||||||
for(Flowfield data : threadList){
|
for(Flowfield data : threadList){
|
||||||
updateFrontier(data, maxUpdate / threadList.size);
|
updateFrontier(data, maxUpdate / threadList.size);
|
||||||
|
|
||||||
//TODO implement timeouts... or don't
|
|
||||||
/*
|
|
||||||
//remove flowfields that have 'timed out' so they can be garbage collected and no longer waste space
|
|
||||||
if(data.refreshRate > 0 && Time.timeSinceMillis(data.lastUpdateTime) > fieldTimeout){
|
|
||||||
//make sure it doesn't get removed twice
|
|
||||||
data.lastUpdateTime = Time.millis();
|
|
||||||
|
|
||||||
Team team = data.team;
|
|
||||||
|
|
||||||
Core.app.post(() -> {
|
|
||||||
//remove its used state
|
|
||||||
if(fieldMap[team.id] != null){
|
|
||||||
fieldMap[team.id].remove(data.target);
|
|
||||||
fieldMapUsed[team.id].remove(data.target);
|
|
||||||
}
|
|
||||||
//remove from main thread list
|
|
||||||
mainList.remove(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
queue.post(() -> {
|
|
||||||
//remove from this thread list with a delay
|
|
||||||
threadList.remove(data);
|
|
||||||
});
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class WaveSpawner{
|
|||||||
for(int i = 0; i < spawned; i++){
|
for(int i = 0; i < spawned; i++){
|
||||||
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
|
Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1);
|
||||||
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
|
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
|
||||||
unit.add();
|
spawnEffect(unit);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
@@ -92,7 +92,7 @@ public class WaveSpawner{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Time.runTask(121f, () -> spawning = false);
|
Time.run(121f, () -> spawning = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doShockwave(float x, float y){
|
public void doShockwave(float x, float y){
|
||||||
@@ -148,8 +148,7 @@ public class WaveSpawner{
|
|||||||
|
|
||||||
private void eachFlyerSpawn(Floatc2 cons){
|
private void eachFlyerSpawn(Floatc2 cons){
|
||||||
for(Tile tile : spawns){
|
for(Tile tile : spawns){
|
||||||
float angle = Angles.angle(world.width() / 2, world.height() / 2, tile.x, tile.y);
|
float angle = Angles.angle(world.width() / 2f, world.height() / 2f, tile.x, tile.y);
|
||||||
|
|
||||||
float trns = Math.max(world.width(), world.height()) * Mathf.sqrt2 * tilesize;
|
float trns = Math.max(world.width(), world.height()) * Mathf.sqrt2 * tilesize;
|
||||||
float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(angle, trns), -margin, world.width() * tilesize + margin);
|
float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(angle, trns), -margin, world.width() * tilesize + margin);
|
||||||
float spawnY = Mathf.clamp(world.height() * tilesize / 2f + Angles.trnsy(angle, trns), -margin, world.height() * tilesize + margin);
|
float spawnY = Mathf.clamp(world.height() * tilesize / 2f + Angles.trnsy(angle, trns), -margin, world.height() * tilesize + margin);
|
||||||
@@ -168,6 +167,7 @@ public class WaveSpawner{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reset(){
|
private void reset(){
|
||||||
|
spawning = false;
|
||||||
spawns.clear();
|
spawns.clear();
|
||||||
|
|
||||||
for(Tile tile : world.tiles){
|
for(Tile tile : world.tiles){
|
||||||
@@ -178,8 +178,11 @@ public class WaveSpawner{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void spawnEffect(Unit unit){
|
private void spawnEffect(Unit unit){
|
||||||
Call.spawnEffect(unit.x, unit.y, unit.type);
|
unit.rotation = unit.angleTo(world.width()/2f * tilesize, world.height()/2f * tilesize);
|
||||||
Time.run(30f, unit::add);
|
unit.apply(StatusEffects.unmoving, 30f);
|
||||||
|
unit.add();
|
||||||
|
|
||||||
|
Call.spawnEffect(unit.x, unit.y, unit.rotation, unit.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface SpawnConsumer{
|
private interface SpawnConsumer{
|
||||||
@@ -187,8 +190,8 @@ public class WaveSpawner{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, unreliable = true)
|
@Remote(called = Loc.server, unreliable = true)
|
||||||
public static void spawnEffect(float x, float y, UnitType type){
|
public static void spawnEffect(float x, float y, float rotation, UnitType u){
|
||||||
Fx.unitSpawn.at(x, y, 0f, type);
|
Fx.unitSpawn.at(x, y, rotation, u);
|
||||||
|
|
||||||
Time.run(30f, () -> Fx.spawn.at(x, y));
|
Time.run(30f, () -> Fx.spawn.at(x, y));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ public class PhysicsProcess implements AsyncProcess{
|
|||||||
|
|
||||||
//find Unit without bodies and assign them
|
//find Unit without bodies and assign them
|
||||||
for(Unit entity : group){
|
for(Unit entity : group){
|
||||||
|
if(entity.type == null) continue;
|
||||||
|
|
||||||
if(entity.physref() == null){
|
if(entity.physref == null){
|
||||||
PhysicsBody body = new PhysicsBody();
|
PhysicsBody body = new PhysicsBody();
|
||||||
body.x = entity.x();
|
body.x = entity.x();
|
||||||
body.y = entity.y();
|
body.y = entity.y();
|
||||||
@@ -48,13 +49,13 @@ public class PhysicsProcess implements AsyncProcess{
|
|||||||
PhysicRef ref = new PhysicRef(entity, body);
|
PhysicRef ref = new PhysicRef(entity, body);
|
||||||
refs.add(ref);
|
refs.add(ref);
|
||||||
|
|
||||||
entity.physref(ref);
|
entity.physref = ref;
|
||||||
|
|
||||||
physics.add(body);
|
physics.add(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
//save last position
|
//save last position
|
||||||
PhysicRef ref = entity.physref();
|
PhysicRef ref = entity.physref;
|
||||||
|
|
||||||
ref.body.layer =
|
ref.body.layer =
|
||||||
entity.type.allowLegStep ? layerLegs :
|
entity.type.allowLegStep ? layerLegs :
|
||||||
|
|||||||
@@ -788,6 +788,7 @@ public class Blocks implements ContentList{
|
|||||||
health = 130 * wallHealthMultiplier;
|
health = 130 * wallHealthMultiplier;
|
||||||
insulated = true;
|
insulated = true;
|
||||||
absorbLasers = true;
|
absorbLasers = true;
|
||||||
|
schematicPriority = 10;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
plastaniumWallLarge = new Wall("plastanium-wall-large"){{
|
plastaniumWallLarge = new Wall("plastanium-wall-large"){{
|
||||||
@@ -796,6 +797,7 @@ public class Blocks implements ContentList{
|
|||||||
size = 2;
|
size = 2;
|
||||||
insulated = true;
|
insulated = true;
|
||||||
absorbLasers = true;
|
absorbLasers = true;
|
||||||
|
schematicPriority = 10;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
thoriumWall = new Wall("thorium-wall"){{
|
thoriumWall = new Wall("thorium-wall"){{
|
||||||
@@ -1398,6 +1400,7 @@ public class Blocks implements ContentList{
|
|||||||
size = 3;
|
size = 3;
|
||||||
itemCapacity = 1000;
|
itemCapacity = 1000;
|
||||||
flags = EnumSet.of(BlockFlag.storage);
|
flags = EnumSet.of(BlockFlag.storage);
|
||||||
|
group = BlockGroup.transportation;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
container = new StorageBlock("container"){{
|
container = new StorageBlock("container"){{
|
||||||
@@ -1405,6 +1408,7 @@ public class Blocks implements ContentList{
|
|||||||
size = 2;
|
size = 2;
|
||||||
itemCapacity = 300;
|
itemCapacity = 300;
|
||||||
flags = EnumSet.of(BlockFlag.storage);
|
flags = EnumSet.of(BlockFlag.storage);
|
||||||
|
group = BlockGroup.transportation;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
unloader = new Unloader("unloader"){{
|
unloader = new Unloader("unloader"){{
|
||||||
@@ -1661,6 +1665,7 @@ public class Blocks implements ContentList{
|
|||||||
shootEffect = Fx.shootLiquid;
|
shootEffect = Fx.shootLiquid;
|
||||||
range = 190f;
|
range = 190f;
|
||||||
health = 250 * size * size;
|
health = 250 * size * size;
|
||||||
|
flags = EnumSet.of(BlockFlag.turret, BlockFlag.extinguisher);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
fuse = new ItemTurret("fuse"){{
|
fuse = new ItemTurret("fuse"){{
|
||||||
|
|||||||
@@ -26,17 +26,23 @@ public class Fx{
|
|||||||
none = new Effect(0, 0f, e -> {}),
|
none = new Effect(0, 0f, e -> {}),
|
||||||
|
|
||||||
unitSpawn = new Effect(30f, e -> {
|
unitSpawn = new Effect(30f, e -> {
|
||||||
if(!(e.data instanceof UnitType)) return;
|
if(!(e.data instanceof UnitType unit)) return;
|
||||||
|
|
||||||
alpha(e.fin());
|
|
||||||
|
|
||||||
float scl = 1f + e.fout() * 2f;
|
float scl = 1f + e.fout() * 2f;
|
||||||
|
|
||||||
UnitType unit = e.data();
|
|
||||||
TextureRegion region = unit.icon(Cicon.full);
|
TextureRegion region = unit.icon(Cicon.full);
|
||||||
|
|
||||||
|
alpha(e.fout());
|
||||||
|
mixcol(Color.white, e.fin());
|
||||||
|
|
||||||
|
rect(region, e.x, e.y, 180f);
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
alpha(e.fin());
|
||||||
|
|
||||||
rect(region, e.x, e.y,
|
rect(region, e.x, e.y,
|
||||||
region.width * Draw.scl * scl, region.height * Draw.scl * scl, 180f);
|
region.width * Draw.scl * scl, region.height * Draw.scl * scl, e.rotation - 90);
|
||||||
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -718,6 +724,19 @@ public class Fx{
|
|||||||
Lines.circle(e.x, e.y, 5f * e.fout());
|
Lines.circle(e.x, e.y, 5f * e.fout());
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
forceShrink = new Effect(20, e -> {
|
||||||
|
color(e.color, e.fout());
|
||||||
|
if(renderer.animateShields){
|
||||||
|
Fill.poly(e.x, e.y, 6, e.rotation * e.fout());
|
||||||
|
}else{
|
||||||
|
stroke(1.5f);
|
||||||
|
Draw.alpha(0.09f);
|
||||||
|
Fill.poly(e.x, e.y, 6, e.rotation * e.fout());
|
||||||
|
Draw.alpha(1f);
|
||||||
|
Lines.poly(e.x, e.y, 6, e.rotation * e.fout());
|
||||||
|
}
|
||||||
|
}).layer(Layer.shields),
|
||||||
|
|
||||||
flakExplosionBig = new Effect(30, e -> {
|
flakExplosionBig = new Effect(30, e -> {
|
||||||
color(Pal.bulletYellowBack);
|
color(Pal.bulletYellowBack);
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public class Items implements ContentList{
|
|||||||
|
|
||||||
surgeAlloy = new Item("surge-alloy", Color.valueOf("f3e979")){{
|
surgeAlloy = new Item("surge-alloy", Color.valueOf("f3e979")){{
|
||||||
cost = 1.2f;
|
cost = 1.2f;
|
||||||
|
charge = 0.75f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{
|
sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class StatusEffects implements ContentList{
|
|||||||
|
|
||||||
burning = new StatusEffect("burning"){{
|
burning = new StatusEffect("burning"){{
|
||||||
color = Pal.lightFlame;
|
color = Pal.lightFlame;
|
||||||
damage = 0.12f; //over 8 seconds, this would be 60 damage
|
damage = 0.12f; //over 8 seconds, this would be ~60 damage
|
||||||
effect = Fx.burning;
|
effect = Fx.burning;
|
||||||
|
|
||||||
init(() -> {
|
init(() -> {
|
||||||
@@ -29,7 +29,7 @@ public class StatusEffects implements ContentList{
|
|||||||
trans(tarred, ((unit, time, newTime, result) -> {
|
trans(tarred, ((unit, time, newTime, result) -> {
|
||||||
unit.damagePierce(8f);
|
unit.damagePierce(8f);
|
||||||
Fx.burning.at(unit.x + Mathf.range(unit.bounds() / 2f), unit.y + Mathf.range(unit.bounds() / 2f));
|
Fx.burning.at(unit.x + Mathf.range(unit.bounds() / 2f), unit.y + Mathf.range(unit.bounds() / 2f));
|
||||||
result.set(this, Math.min(time + newTime, 300f));
|
result.set(burning, Math.min(time + newTime, 300f));
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}};
|
}};
|
||||||
@@ -45,7 +45,7 @@ public class StatusEffects implements ContentList{
|
|||||||
|
|
||||||
trans(blasted, ((unit, time, newTime, result) -> {
|
trans(blasted, ((unit, time, newTime, result) -> {
|
||||||
unit.damagePierce(18f);
|
unit.damagePierce(18f);
|
||||||
result.set(this, time);
|
result.set(freezing, time);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}};
|
}};
|
||||||
@@ -72,7 +72,7 @@ public class StatusEffects implements ContentList{
|
|||||||
if(unit.team == state.rules.waveTeam){
|
if(unit.team == state.rules.waveTeam){
|
||||||
Events.fire(Trigger.shock);
|
Events.fire(Trigger.shock);
|
||||||
}
|
}
|
||||||
result.set(this, time);
|
result.set(wet, time);
|
||||||
}));
|
}));
|
||||||
opposite(burning);
|
opposite(burning);
|
||||||
});
|
});
|
||||||
@@ -97,7 +97,7 @@ public class StatusEffects implements ContentList{
|
|||||||
trans(tarred, ((unit, time, newTime, result) -> {
|
trans(tarred, ((unit, time, newTime, result) -> {
|
||||||
unit.damagePierce(8f);
|
unit.damagePierce(8f);
|
||||||
Fx.burning.at(unit.x + Mathf.range(unit.bounds() / 2f), unit.y + Mathf.range(unit.bounds() / 2f));
|
Fx.burning.at(unit.x + Mathf.range(unit.bounds() / 2f), unit.y + Mathf.range(unit.bounds() / 2f));
|
||||||
result.set(this, Math.min(time + newTime, 200f));
|
result.set(melting, Math.min(time + newTime, 200f));
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}};
|
}};
|
||||||
@@ -161,10 +161,12 @@ public class StatusEffects implements ContentList{
|
|||||||
|
|
||||||
shocked = new StatusEffect("shocked"){{
|
shocked = new StatusEffect("shocked"){{
|
||||||
color = Pal.lancerLaser;
|
color = Pal.lancerLaser;
|
||||||
|
reactive = true;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
blasted = new StatusEffect("blasted"){{
|
blasted = new StatusEffect("blasted"){{
|
||||||
color = Color.valueOf("ff795e");
|
color = Color.valueOf("ff795e");
|
||||||
|
reactive = true;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
corroded = new StatusEffect("corroded"){{
|
corroded = new StatusEffect("corroded"){{
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public class UnitTypes implements ContentList{
|
|||||||
hitSize = 13f;
|
hitSize = 13f;
|
||||||
rotateSpeed = 3f;
|
rotateSpeed = 3f;
|
||||||
targetAir = false;
|
targetAir = false;
|
||||||
health = 790;
|
health = 800;
|
||||||
armor = 9f;
|
armor = 9f;
|
||||||
mechFrontSway = 0.55f;
|
mechFrontSway = 0.55f;
|
||||||
|
|
||||||
@@ -137,8 +137,8 @@ public class UnitTypes implements ContentList{
|
|||||||
width = height = 14f;
|
width = height = 14f;
|
||||||
collides = true;
|
collides = true;
|
||||||
collidesTiles = true;
|
collidesTiles = true;
|
||||||
splashDamageRadius = 24f;
|
splashDamageRadius = 28f;
|
||||||
splashDamage = 45f;
|
splashDamage = 54f;
|
||||||
backColor = Pal.bulletYellowBack;
|
backColor = Pal.bulletYellowBack;
|
||||||
frontColor = Pal.bulletYellow;
|
frontColor = Pal.bulletYellow;
|
||||||
}};
|
}};
|
||||||
@@ -150,7 +150,7 @@ public class UnitTypes implements ContentList{
|
|||||||
hitSize = 20f;
|
hitSize = 20f;
|
||||||
rotateSpeed = 2.1f;
|
rotateSpeed = 2.1f;
|
||||||
health = 9000;
|
health = 9000;
|
||||||
armor = 11f;
|
armor = 10f;
|
||||||
canDrown = false;
|
canDrown = false;
|
||||||
mechFrontSway = 1f;
|
mechFrontSway = 1f;
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ public class UnitTypes implements ContentList{
|
|||||||
inaccuracy = 3f;
|
inaccuracy = 3f;
|
||||||
shotDelay = 4f;
|
shotDelay = 4f;
|
||||||
|
|
||||||
bullet = new BasicBulletType(7f, 50){{
|
bullet = new BasicBulletType(7f, 45){{
|
||||||
width = 11f;
|
width = 11f;
|
||||||
height = 20f;
|
height = 20f;
|
||||||
lifetime = 25f;
|
lifetime = 25f;
|
||||||
@@ -182,7 +182,7 @@ public class UnitTypes implements ContentList{
|
|||||||
lightningLength = 6;
|
lightningLength = 6;
|
||||||
lightningColor = Pal.surge;
|
lightningColor = Pal.surge;
|
||||||
//standard bullet damage is far too much for lightning
|
//standard bullet damage is far too much for lightning
|
||||||
lightningDamage = 20;
|
lightningDamage = 19;
|
||||||
}};
|
}};
|
||||||
}},
|
}},
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ public class UnitTypes implements ContentList{
|
|||||||
ejectEffect = Fx.casing4;
|
ejectEffect = Fx.casing4;
|
||||||
shootSound = Sounds.bang;
|
shootSound = Sounds.bang;
|
||||||
|
|
||||||
bullet = new BasicBulletType(13f, 60){{
|
bullet = new BasicBulletType(13f, 65){{
|
||||||
pierce = true;
|
pierce = true;
|
||||||
pierceCap = 10;
|
pierceCap = 10;
|
||||||
width = 14f;
|
width = 14f;
|
||||||
@@ -247,7 +247,7 @@ public class UnitTypes implements ContentList{
|
|||||||
fragLifeMin = 0f;
|
fragLifeMin = 0f;
|
||||||
fragCone = 30f;
|
fragCone = 30f;
|
||||||
|
|
||||||
fragBullet = new BasicBulletType(9f, 15){{
|
fragBullet = new BasicBulletType(9f, 18){{
|
||||||
width = 10f;
|
width = 10f;
|
||||||
height = 10f;
|
height = 10f;
|
||||||
pierce = true;
|
pierce = true;
|
||||||
@@ -418,8 +418,8 @@ public class UnitTypes implements ContentList{
|
|||||||
engineSize = 6f;
|
engineSize = 6f;
|
||||||
lowAltitude = true;
|
lowAltitude = true;
|
||||||
|
|
||||||
health = 7000f;
|
health = 7200f;
|
||||||
armor = 7f;
|
armor = 8f;
|
||||||
canBoost = true;
|
canBoost = true;
|
||||||
landShake = 4f;
|
landShake = 4f;
|
||||||
immunities = ObjectSet.with(StatusEffects.burning);
|
immunities = ObjectSet.with(StatusEffects.burning);
|
||||||
@@ -435,7 +435,7 @@ public class UnitTypes implements ContentList{
|
|||||||
|
|
||||||
firstShotDelay = Fx.greenLaserChargeSmall.lifetime - 1f;
|
firstShotDelay = Fx.greenLaserChargeSmall.lifetime - 1f;
|
||||||
|
|
||||||
reload = 160f;
|
reload = 155f;
|
||||||
recoil = 0f;
|
recoil = 0f;
|
||||||
chargeSound = Sounds.lasercharge2;
|
chargeSound = Sounds.lasercharge2;
|
||||||
shootSound = Sounds.beam;
|
shootSound = Sounds.beam;
|
||||||
@@ -443,8 +443,8 @@ public class UnitTypes implements ContentList{
|
|||||||
cooldownTime = 200f;
|
cooldownTime = 200f;
|
||||||
|
|
||||||
bullet = new ContinuousLaserBulletType(){{
|
bullet = new ContinuousLaserBulletType(){{
|
||||||
damage = 23f;
|
damage = 26f;
|
||||||
length = 160f;
|
length = 170f;
|
||||||
hitEffect = Fx.hitMeltHeal;
|
hitEffect = Fx.hitMeltHeal;
|
||||||
drawSize = 420f;
|
drawSize = 420f;
|
||||||
lifetime = 160f;
|
lifetime = 160f;
|
||||||
@@ -454,7 +454,7 @@ public class UnitTypes implements ContentList{
|
|||||||
|
|
||||||
shootEffect = Fx.greenLaserChargeSmall;
|
shootEffect = Fx.greenLaserChargeSmall;
|
||||||
|
|
||||||
incendChance = 0.075f;
|
incendChance = 0.08f;
|
||||||
incendSpread = 5f;
|
incendSpread = 5f;
|
||||||
incendAmount = 1;
|
incendAmount = 1;
|
||||||
|
|
||||||
@@ -1590,7 +1590,7 @@ public class UnitTypes implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
sei = new UnitType("sei"){{
|
sei = new UnitType("sei"){{
|
||||||
health = 10000;
|
health = 10500;
|
||||||
armor = 12f;
|
armor = 12f;
|
||||||
|
|
||||||
speed = 0.73f;
|
speed = 0.73f;
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ public class Logic implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void skipWave(){
|
public void skipWave(){
|
||||||
state.wavetime = 0;
|
runWave();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void runWave(){
|
public void runWave(){
|
||||||
|
|||||||
@@ -396,7 +396,6 @@ public class NetClient implements ApplicationListener{
|
|||||||
netClient.byteStream.setBytes(net.decompressSnapshot(data, dataLen));
|
netClient.byteStream.setBytes(net.decompressSnapshot(data, dataLen));
|
||||||
DataInputStream input = netClient.dataStream;
|
DataInputStream input = netClient.dataStream;
|
||||||
|
|
||||||
//go through each entity
|
|
||||||
for(int j = 0; j < amount; j++){
|
for(int j = 0; j < amount; j++){
|
||||||
int id = input.readInt();
|
int id = input.readInt();
|
||||||
byte typeID = input.readByte();
|
byte typeID = input.readByte();
|
||||||
@@ -445,11 +444,16 @@ public class NetClient implements ApplicationListener{
|
|||||||
|
|
||||||
for(int i = 0; i < amount; i++){
|
for(int i = 0; i < amount; i++){
|
||||||
int pos = input.readInt();
|
int pos = input.readInt();
|
||||||
|
short block = input.readShort();
|
||||||
Tile tile = world.tile(pos);
|
Tile tile = world.tile(pos);
|
||||||
if(tile == null || tile.build == null){
|
if(tile == null || tile.build == null){
|
||||||
Log.warn("Missing entity at @. Skipping block snapshot.", tile);
|
Log.warn("Missing entity at @. Skipping block snapshot.", tile);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(tile.build.block.id != block){
|
||||||
|
Log.warn("Block ID mismatch at @: @ != @. Skipping block snapshot.", tile, tile.build.block.id, block);
|
||||||
|
break;
|
||||||
|
}
|
||||||
tile.build.readAll(Reads.get(input), tile.build.version());
|
tile.build.readAll(Reads.get(input), tile.build.version());
|
||||||
}
|
}
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
if(!extraMods.isEmpty()){
|
if(!extraMods.isEmpty()){
|
||||||
result.append("Unnecessary mods:[lightgray]\n").append("> ").append(extraMods.toString("\n> "));
|
result.append("Unnecessary mods:[lightgray]\n").append("> ").append(extraMods.toString("\n> "));
|
||||||
}
|
}
|
||||||
con.kick(result.toString());
|
con.kick(result.toString(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!admins.isWhitelisted(packet.uuid, packet.usid)){
|
if(!admins.isWhitelisted(packet.uuid, packet.usid)){
|
||||||
@@ -182,7 +182,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Groups.player.contains(player -> player.uuid().equals(packet.uuid) || player.usid().equals(packet.usid) || player.ip().equals(con.address))){
|
if(Groups.player.contains(player -> player.uuid().equals(packet.uuid) || player.usid().equals(packet.usid))){
|
||||||
con.kick(KickReason.idInUse);
|
con.kick(KickReason.idInUse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -824,6 +824,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
sent ++;
|
sent ++;
|
||||||
|
|
||||||
dataStream.writeInt(entity.pos());
|
dataStream.writeInt(entity.pos());
|
||||||
|
dataStream.writeShort(entity.block.id);
|
||||||
entity.writeAll(Writes.get(dataStream));
|
entity.writeAll(Writes.get(dataStream));
|
||||||
|
|
||||||
if(syncStream.size() > maxSnapshotSize){
|
if(syncStream.size() > maxSnapshotSize){
|
||||||
@@ -844,13 +845,15 @@ public class NetServer implements ApplicationListener{
|
|||||||
|
|
||||||
public void writeEntitySnapshot(Player player) throws IOException{
|
public void writeEntitySnapshot(Player player) throws IOException{
|
||||||
syncStream.reset();
|
syncStream.reset();
|
||||||
Seq<CoreBuild> cores = state.teams.cores(player.team());
|
int sum = state.teams.present.sum(t -> t.cores.size);
|
||||||
|
|
||||||
dataStream.writeByte(cores.size);
|
dataStream.writeByte(sum);
|
||||||
|
|
||||||
for(CoreBuild entity : cores){
|
for(TeamData data : state.teams.present){
|
||||||
dataStream.writeInt(entity.tile.pos());
|
for(CoreBuild entity : data.cores){
|
||||||
entity.items.write(Writes.get(dataStream));
|
dataStream.writeInt(entity.tile.pos());
|
||||||
|
entity.items.write(Writes.get(dataStream));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dataStream.close();
|
dataStream.close();
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package mindustry.core;
|
|||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
import arc.fx.*;
|
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.graphics.gl.*;
|
import arc.graphics.gl.*;
|
||||||
@@ -38,13 +37,8 @@ public class Renderer implements ApplicationListener{
|
|||||||
public float minZoom = 1.5f, maxZoom = 6f;
|
public float minZoom = 1.5f, maxZoom = 6f;
|
||||||
|
|
||||||
private @Nullable CoreBuild landCore;
|
private @Nullable CoreBuild landCore;
|
||||||
//TODO unused
|
|
||||||
private FxProcessor fx = new FxProcessor();
|
|
||||||
private Color clearColor = new Color(0f, 0f, 0f, 1f);
|
private Color clearColor = new Color(0f, 0f, 0f, 1f);
|
||||||
private float targetscale = Scl.scl(4);
|
private float targetscale = Scl.scl(4), camerascale = targetscale, landscale, landTime, weatherAlpha, minZoomScl = Scl.scl(0.01f);
|
||||||
private float camerascale = targetscale;
|
|
||||||
private float landscale = 0f, landTime, weatherAlpha;
|
|
||||||
private float minZoomScl = Scl.scl(0.01f);
|
|
||||||
private float shakeIntensity, shaketime;
|
private float shakeIntensity, shaketime;
|
||||||
|
|
||||||
public Renderer(){
|
public Renderer(){
|
||||||
@@ -136,11 +130,6 @@ public class Renderer implements ApplicationListener{
|
|||||||
Events.fire(new DisposeEvent());
|
Events.fire(new DisposeEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resize(int width, int height){
|
|
||||||
fx.resize(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resume(){
|
public void resume(){
|
||||||
if(settings.getBool("bloom") && bloom != null){
|
if(settings.getBool("bloom") && bloom != null){
|
||||||
@@ -175,23 +164,6 @@ public class Renderer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void beginFx(){
|
|
||||||
if(!fx.hasEnabledEffects()) return;
|
|
||||||
|
|
||||||
Draw.flush();
|
|
||||||
fx.clear();
|
|
||||||
fx.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void endFx(){
|
|
||||||
if(!fx.hasEnabledEffects()) return;
|
|
||||||
|
|
||||||
Draw.flush();
|
|
||||||
fx.end();
|
|
||||||
fx.applyEffects();
|
|
||||||
fx.render(0, 0, fx.getWidth(), fx.getHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateShake(float scale){
|
void updateShake(float scale){
|
||||||
if(shaketime > 0){
|
if(shaketime > 0){
|
||||||
float intensity = shakeIntensity * (settings.getInt("screenshake", 4) / 4f) * scale;
|
float intensity = shakeIntensity * (settings.getInt("screenshake", 4) / 4f) * scale;
|
||||||
|
|||||||
@@ -214,6 +214,13 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
@Override
|
@Override
|
||||||
public void resize(int width, int height){
|
public void resize(int width, int height){
|
||||||
if(Core.scene == null) return;
|
if(Core.scene == null) return;
|
||||||
|
|
||||||
|
int[] insets = Core.graphics.getSafeInsets();
|
||||||
|
Core.scene.marginLeft = insets[0];
|
||||||
|
Core.scene.marginRight = insets[1];
|
||||||
|
Core.scene.marginTop = insets[2];
|
||||||
|
Core.scene.marginBottom = insets[3];
|
||||||
|
|
||||||
Core.scene.resize(width, height);
|
Core.scene.resize(width, height);
|
||||||
Events.fire(new ResizeEvent());
|
Events.fire(new ResizeEvent());
|
||||||
}
|
}
|
||||||
@@ -363,6 +370,16 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
}}.show();
|
}}.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showInfoOnHidden(String info, Runnable listener){
|
||||||
|
new Dialog(""){{
|
||||||
|
getCell(cont).growX();
|
||||||
|
cont.margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
|
||||||
|
buttons.button("@ok", this::hide).size(110, 50).pad(4);
|
||||||
|
hidden(listener);
|
||||||
|
closeOnBack();
|
||||||
|
}}.show();
|
||||||
|
}
|
||||||
|
|
||||||
public void showStartupInfo(String info){
|
public void showStartupInfo(String info){
|
||||||
new Dialog(""){{
|
new Dialog(""){{
|
||||||
getCell(cont).growX();
|
getCell(cont).growX();
|
||||||
@@ -526,16 +543,15 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO move?
|
|
||||||
|
|
||||||
public static String formatAmount(int number){
|
public static String formatAmount(int number){
|
||||||
if(number >= 1_000_000_000){
|
int mag = Math.abs(number);
|
||||||
|
if(mag >= 1_000_000_000){
|
||||||
return Strings.fixed(number / 1_000_000_000f, 1) + "[gray]" + Core.bundle.get("unit.billions") + "[]";
|
return Strings.fixed(number / 1_000_000_000f, 1) + "[gray]" + Core.bundle.get("unit.billions") + "[]";
|
||||||
}else if(number >= 1_000_000){
|
}else if(mag >= 1_000_000){
|
||||||
return Strings.fixed(number / 1_000_000f, 1) + "[gray]" + Core.bundle.get("unit.millions") + "[]";
|
return Strings.fixed(number / 1_000_000f, 1) + "[gray]" + Core.bundle.get("unit.millions") + "[]";
|
||||||
}else if(number >= 10_000){
|
}else if(mag >= 10_000){
|
||||||
return number / 1000 + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
|
return number / 1000 + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
|
||||||
}else if(number >= 1000){
|
}else if(mag >= 1000){
|
||||||
return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
|
return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
|
||||||
}else{
|
}else{
|
||||||
return number + "";
|
return number + "";
|
||||||
|
|||||||
@@ -263,7 +263,9 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
|
|
||||||
if(player.team().core() == null){
|
if(player.team().core() == null){
|
||||||
player.set(world.width() * tilesize/2f, world.height() * tilesize/2f);
|
player.set(world.width() * tilesize/2f, world.height() * tilesize/2f);
|
||||||
player.unit(UnitTypes.alpha.spawn(player.team(), player.x, player.y));
|
var unit = UnitTypes.alpha.spawn(player.team(), player.x, player.y);
|
||||||
|
unit.spawnedByCore = true;
|
||||||
|
player.unit(unit);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,29 +285,31 @@ public class MapGenerateDialog extends BaseDialog{
|
|||||||
|
|
||||||
void showAdd(){
|
void showAdd(){
|
||||||
BaseDialog selection = new BaseDialog("@add");
|
BaseDialog selection = new BaseDialog("@add");
|
||||||
selection.setFillParent(false);
|
selection.cont.pane(p -> {
|
||||||
selection.cont.defaults().size(210f, 60f);
|
p.marginRight(14);
|
||||||
int i = 0;
|
p.defaults().size(210f, 60f);
|
||||||
for(Prov<GenerateFilter> gen : filterTypes){
|
int i = 0;
|
||||||
GenerateFilter filter = gen.get();
|
for(Prov<GenerateFilter> gen : filterTypes){
|
||||||
|
GenerateFilter filter = gen.get();
|
||||||
|
|
||||||
if((filter.isPost() && applied)) continue;
|
if((filter.isPost() && applied)) continue;
|
||||||
|
|
||||||
selection.cont.button(filter.name(), () -> {
|
p.button(filter.name(), () -> {
|
||||||
filters.add(filter);
|
filters.add(filter);
|
||||||
|
rebuildFilters();
|
||||||
|
update();
|
||||||
|
selection.hide();
|
||||||
|
});
|
||||||
|
if(++i % 2 == 0) p.row();
|
||||||
|
}
|
||||||
|
|
||||||
|
p.button("@filter.defaultores", () -> {
|
||||||
|
maps.addDefaultOres(filters);
|
||||||
rebuildFilters();
|
rebuildFilters();
|
||||||
update();
|
update();
|
||||||
selection.hide();
|
selection.hide();
|
||||||
});
|
});
|
||||||
if(++i % 2 == 0) selection.cont.row();
|
}).get().setScrollingDisabled(true, false);
|
||||||
}
|
|
||||||
|
|
||||||
selection.cont.button("@filter.defaultores", () -> {
|
|
||||||
maps.addDefaultOres(filters);
|
|
||||||
rebuildFilters();
|
|
||||||
update();
|
|
||||||
selection.hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
selection.addCloseButton();
|
selection.addCloseButton();
|
||||||
selection.show();
|
selection.show();
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ public class Damage{
|
|||||||
/** Creates a dynamic explosion based on specified parameters. */
|
/** Creates a dynamic explosion based on specified parameters. */
|
||||||
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage, boolean fire, @Nullable Team ignoreTeam){
|
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, boolean damage, boolean fire, @Nullable Team ignoreTeam){
|
||||||
if(damage){
|
if(damage){
|
||||||
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){
|
for(int i = 0; i < Mathf.clamp(power / 700, 0, 8); i++){
|
||||||
int branches = 5 + Mathf.clamp((int)(power / 30), 1, 20);
|
int length = 5 + Mathf.clamp((int)(power / 500), 1, 20);
|
||||||
Time.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), branches + Mathf.range(2)));
|
Time.run(i * 0.8f + Mathf.random(4f), () -> Lightning.create(Team.derelict, Pal.power, 3, x, y, Mathf.random(360f), length + Mathf.range(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fire){
|
if(fire){
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package mindustry.entities;
|
|||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
|
import mindustry.content.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ public class EntityCollisions{
|
|||||||
|
|
||||||
public static boolean legsSolid(int x, int y){
|
public static boolean legsSolid(int x, int y){
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
return tile == null || tile.staticDarkness() >= 2 || tile.floor().solid;
|
return tile == null || tile.staticDarkness() >= 2 || (tile.floor().solid && tile.block() == Blocks.air);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean waterSolid(int x, int y){
|
public static boolean waterSolid(int x, int y){
|
||||||
@@ -190,14 +191,10 @@ public class EntityCollisions{
|
|||||||
yInvExit = y2 - (y1 + h1);
|
yInvExit = y2 - (y1 + h1);
|
||||||
}
|
}
|
||||||
|
|
||||||
float xEntry, yEntry;
|
float xEntry = xInvEntry / vx1;
|
||||||
float xExit, yExit;
|
float xExit = xInvExit / vx1;
|
||||||
|
float yEntry = yInvEntry / vy1;
|
||||||
xEntry = xInvEntry / vx1;
|
float yExit = yInvExit / vy1;
|
||||||
xExit = xInvExit / vx1;
|
|
||||||
|
|
||||||
yEntry = yInvEntry / vy1;
|
|
||||||
yExit = yInvExit / vy1;
|
|
||||||
|
|
||||||
float entryTime = Math.max(xEntry, yEntry);
|
float entryTime = Math.max(xEntry, yEntry);
|
||||||
float exitTime = Math.min(xExit, yExit);
|
float exitTime = Math.min(xExit, yExit);
|
||||||
|
|||||||
@@ -536,6 +536,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dumpLiquid(Liquid liquid){
|
public void dumpLiquid(Liquid liquid){
|
||||||
|
dumpLiquid(liquid, 2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dumpLiquid(Liquid liquid, float scaling){
|
||||||
int dump = this.cdump;
|
int dump = this.cdump;
|
||||||
|
|
||||||
if(liquids.get(liquid) <= 0.0001f) return;
|
if(liquids.get(liquid) <= 0.0001f) return;
|
||||||
@@ -551,10 +555,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
float ofract = other.liquids.get(liquid) / other.block.liquidCapacity;
|
float ofract = other.liquids.get(liquid) / other.block.liquidCapacity;
|
||||||
float fract = liquids.get(liquid) / block.liquidCapacity;
|
float fract = liquids.get(liquid) / block.liquidCapacity;
|
||||||
|
|
||||||
if(ofract < fract) transferLiquid(other, (fract - ofract) * block.liquidCapacity / 2f, liquid);
|
if(ofract < fract) transferLiquid(other, (fract - ofract) * block.liquidCapacity / scaling, liquid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canDumpLiquid(Building to, Liquid liquid){
|
public boolean canDumpLiquid(Building to, Liquid liquid){
|
||||||
@@ -979,6 +982,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
int amount = items.get(item);
|
int amount = items.get(item);
|
||||||
explosiveness += item.explosiveness * amount;
|
explosiveness += item.explosiveness * amount;
|
||||||
flammability += item.flammability * amount;
|
flammability += item.flammability * amount;
|
||||||
|
power += item.charge * amount * 100f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1306,6 +1310,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
case health -> health;
|
case health -> health;
|
||||||
case maxHealth -> maxHealth;
|
case maxHealth -> maxHealth;
|
||||||
case efficiency -> efficiency();
|
case efficiency -> efficiency();
|
||||||
|
case timescale -> timeScale;
|
||||||
|
case range -> this instanceof Ranged r ? r.range() / tilesize : 0;
|
||||||
case rotation -> rotation;
|
case rotation -> rotation;
|
||||||
case totalItems -> items == null ? 0 : items.total();
|
case totalItems -> items == null ? 0 : items.total();
|
||||||
case totalLiquids -> liquids == null ? 0 : liquids.total();
|
case totalLiquids -> liquids == null ? 0 : liquids.total();
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ abstract class CommanderComp implements Entityc, Posc{
|
|||||||
|
|
||||||
void command(Formation formation, Seq<Unit> units){
|
void command(Formation formation, Seq<Unit> units){
|
||||||
clearCommand();
|
clearCommand();
|
||||||
|
units.shuffle();
|
||||||
|
|
||||||
float spacing = hitSize * 0.8f;
|
float spacing = hitSize * 0.8f;
|
||||||
minFormationSpeed = type.speed;
|
minFormationSpeed = type.speed;
|
||||||
|
|||||||
@@ -55,10 +55,16 @@ abstract class StatusComp implements Posc, Flyingc{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise, no opposites found, add direct effect
|
if(!effect.reactive){
|
||||||
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
//otherwise, no opposites found, add direct effect
|
||||||
entry.set(effect, duration);
|
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
|
||||||
statuses.add(entry);
|
entry.set(effect, duration);
|
||||||
|
statuses.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearStatuses(){
|
||||||
|
statuses.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes a status effect. */
|
/** Removes a status effect. */
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void approach(Vec2 vector){
|
public void approach(Vec2 vector){
|
||||||
vel.approachDelta(vector, type.accel * realSpeed() * floorSpeedMultiplier());
|
vel.approachDelta(vector, type.accel * realSpeed());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void aimLook(Position pos){
|
public void aimLook(Position pos){
|
||||||
@@ -82,7 +82,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
|
|
||||||
/** @return speed with boost multipliers factored in. */
|
/** @return speed with boost multipliers factored in. */
|
||||||
public float realSpeed(){
|
public float realSpeed(){
|
||||||
return Mathf.lerp(1f, type.canBoost ? type.boostMultiplier : 1f, elevation) * speed();
|
return Mathf.lerp(1f, type.canBoost ? type.boostMultiplier : 1f, elevation) * speed() * floorSpeedMultiplier();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Iterates through this unit and everything it is controlling. */
|
/** Iterates through this unit and everything it is controlling. */
|
||||||
@@ -130,6 +130,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
case y -> World.conv(y);
|
case y -> World.conv(y);
|
||||||
case team -> team.id;
|
case team -> team.id;
|
||||||
case shooting -> isShooting() ? 1 : 0;
|
case shooting -> isShooting() ? 1 : 0;
|
||||||
|
case range -> range() / tilesize;
|
||||||
case shootX -> World.conv(aimX());
|
case shootX -> World.conv(aimX());
|
||||||
case shootY -> World.conv(aimY());
|
case shootY -> World.conv(aimY());
|
||||||
case mining -> mining() ? 1 : 0;
|
case mining -> mining() ? 1 : 0;
|
||||||
@@ -410,9 +411,10 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
|
|
||||||
float explosiveness = 2f + item().explosiveness * stack().amount * 1.53f;
|
float explosiveness = 2f + item().explosiveness * stack().amount * 1.53f;
|
||||||
float flammability = item().flammability * stack().amount / 1.9f;
|
float flammability = item().flammability * stack().amount / 1.9f;
|
||||||
|
float power = item().charge * stack().amount * 150f;
|
||||||
|
|
||||||
if(!spawnedByCore){
|
if(!spawnedByCore){
|
||||||
Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, state.rules.damageExplosions, item().flammability > 1, team);
|
Damage.dynamicExplosion(x, y, flammability, explosiveness, power, bounds() / 2f, state.rules.damageExplosions, item().flammability > 1, team);
|
||||||
}
|
}
|
||||||
|
|
||||||
float shake = hitSize / 3f;
|
float shake = hitSize / 3f;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package mindustry.entities.comp;
|
package mindustry.entities.comp;
|
||||||
|
|
||||||
import arc.math.*;
|
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
@@ -22,7 +21,7 @@ abstract class VelComp implements Posc{
|
|||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
move(vel.x * Time.delta, vel.y * Time.delta);
|
move(vel.x * Time.delta, vel.y * Time.delta);
|
||||||
vel.scl(Mathf.clamp(1f - drag * Time.delta));
|
vel.scl(Math.max(1f - drag * Time.delta, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return function to use for check solid state. if null, no checking is done. */
|
/** @return function to use for check solid state. if null, no checking is done. */
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public class MultiEffect extends Effect{
|
|||||||
public void init(){
|
public void init(){
|
||||||
for(Effect f : effects){
|
for(Effect f : effects){
|
||||||
clip = Math.max(clip, f.clip);
|
clip = Math.max(clip, f.clip);
|
||||||
|
lifetime = Math.max(lifetime, f.lifetime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public class ParticleEffect extends Effect{
|
|||||||
|
|
||||||
//region only
|
//region only
|
||||||
public float sizeFrom = 2f, sizeTo = 0f;
|
public float sizeFrom = 2f, sizeTo = 0f;
|
||||||
|
public float offset = 0;
|
||||||
public String region = "circle";
|
public String region = "circle";
|
||||||
|
|
||||||
//line only
|
//line only
|
||||||
@@ -48,7 +49,7 @@ public class ParticleEffect extends Effect{
|
|||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
Angles.randLenVectors(e.id, particles, length * fin + baseLength, e.rotation, cone, (x, y) -> {
|
Angles.randLenVectors(e.id, particles, length * fin + baseLength, e.rotation, cone, (x, y) -> {
|
||||||
Draw.rect(tex, e.x + x, e.y + y, rad, rad);
|
Draw.rect(tex, e.x + x, e.y + y, rad, rad, e.rotation + offset);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ public class EventType{
|
|||||||
public static class ContentInitEvent{}
|
public static class ContentInitEvent{}
|
||||||
/** Called when the client game is first loaded. */
|
/** Called when the client game is first loaded. */
|
||||||
public static class ClientLoadEvent{}
|
public static class ClientLoadEvent{}
|
||||||
|
/** Called *after* all the modded files have been added into Vars.tree */
|
||||||
|
public static class FileTreeInitEvent{}
|
||||||
/** Called when a game begins and the world is loaded. */
|
/** Called when a game begins and the world is loaded. */
|
||||||
public static class WorldLoadEvent{}
|
public static class WorldLoadEvent{}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ public enum Gamemode{
|
|||||||
rules.buildCostMultiplier = 1f;
|
rules.buildCostMultiplier = 1f;
|
||||||
rules.buildSpeedMultiplier = 1f;
|
rules.buildSpeedMultiplier = 1f;
|
||||||
rules.unitBuildSpeedMultiplier = 2f;
|
rules.unitBuildSpeedMultiplier = 2f;
|
||||||
rules.unitHealthMultiplier = 3f;
|
|
||||||
rules.attackMode = true;
|
rules.attackMode = true;
|
||||||
}, map -> map.teams.size > 1),
|
}, map -> map.teams.size > 1),
|
||||||
editor(true, rules -> {
|
editor(true, rules -> {
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ public class Rules{
|
|||||||
public boolean unitAmmo = false;
|
public boolean unitAmmo = false;
|
||||||
/** How fast unit pads build units. */
|
/** How fast unit pads build units. */
|
||||||
public float unitBuildSpeedMultiplier = 1f;
|
public float unitBuildSpeedMultiplier = 1f;
|
||||||
/** How much health units start with. */
|
|
||||||
public float unitHealthMultiplier = 1f;
|
|
||||||
/** How much damage any other units deal. */
|
/** How much damage any other units deal. */
|
||||||
public float unitDamageMultiplier = 1f;
|
public float unitDamageMultiplier = 1f;
|
||||||
/** How much health blocks start with. */
|
/** How much health blocks start with. */
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ public class Schematics implements Loadable{
|
|||||||
/** Creates an array of build requests from a schematic's data, centered on the provided x+y coordinates. */
|
/** Creates an array of build requests from a schematic's data, centered on the provided x+y coordinates. */
|
||||||
public Seq<BuildPlan> toRequests(Schematic schem, int x, int y){
|
public Seq<BuildPlan> toRequests(Schematic schem, int x, int y){
|
||||||
return schem.tiles.map(t -> new BuildPlan(t.x + x - schem.width/2, t.y + y - schem.height/2, t.rotation, t.block, t.config).original(t.x, t.y, schem.width, schem.height))
|
return schem.tiles.map(t -> new BuildPlan(t.x + x - schem.width/2, t.y + y - schem.height/2, t.rotation, t.block, t.config).original(t.x, t.y, schem.width, schem.height))
|
||||||
.removeAll(s -> (!s.block.isVisible() && !(s.block instanceof CoreBlock)) || !s.block.unlockedNow());
|
.removeAll(s -> (!s.block.isVisible() && !(s.block instanceof CoreBlock)) || !s.block.unlockedNow()).sort(Structs.comparingInt(s -> -s.block.schematicPriority));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return all the valid loadouts for a specific core type. */
|
/** @return all the valid loadouts for a specific core type. */
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ public class Universe{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return the last selected loadout for this specific core type. */
|
/** @return the last selected loadout for this specific core type. */
|
||||||
|
@Nullable
|
||||||
public Schematic getLoadout(CoreBlock core){
|
public Schematic getLoadout(CoreBlock core){
|
||||||
//for tools - schem
|
//for tools - schem
|
||||||
if(schematics == null) return Loadouts.basicShard;
|
if(schematics == null) return Loadouts.basicShard;
|
||||||
@@ -134,7 +135,7 @@ public class Universe{
|
|||||||
Seq<Schematic> all = schematics.getLoadouts(core);
|
Seq<Schematic> all = schematics.getLoadouts(core);
|
||||||
Schematic schem = all.find(s -> s.file != null && s.file.nameWithoutExtension().equals(file));
|
Schematic schem = all.find(s -> s.file != null && s.file.nameWithoutExtension().equals(file));
|
||||||
|
|
||||||
return schem == null ? all.first() : schem;
|
return schem == null ? all.any() ? all.first() : null : schem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Runs possible events. Resets event counter. */
|
/** Runs possible events. Resets event counter. */
|
||||||
|
|||||||
@@ -221,9 +221,13 @@ public class Drawf{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void construct(float x, float y, TextureRegion region, float rotation, float progress, float speed, float time){
|
public static void construct(float x, float y, TextureRegion region, float rotation, float progress, float speed, float time){
|
||||||
|
construct(x, y, region, Pal.accent, rotation, progress, speed, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void construct(float x, float y, TextureRegion region, Color color, float rotation, float progress, float speed, float time){
|
||||||
Shaders.build.region = region;
|
Shaders.build.region = region;
|
||||||
Shaders.build.progress = progress;
|
Shaders.build.progress = progress;
|
||||||
Shaders.build.color.set(Pal.accent);
|
Shaders.build.color.set(color);
|
||||||
Shaders.build.color.a = speed;
|
Shaders.build.color.a = speed;
|
||||||
Shaders.build.time = -time / 20f;
|
Shaders.build.time = -time / 20f;
|
||||||
|
|
||||||
@@ -235,9 +239,13 @@ public class Drawf{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void construct(Building t, TextureRegion region, float rotation, float progress, float speed, float time){
|
public static void construct(Building t, TextureRegion region, float rotation, float progress, float speed, float time){
|
||||||
|
construct(t, region, Pal.accent, rotation, progress, speed, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void construct(Building t, TextureRegion region, Color color, float rotation, float progress, float speed, float time){
|
||||||
Shaders.build.region = region;
|
Shaders.build.region = region;
|
||||||
Shaders.build.progress = progress;
|
Shaders.build.progress = progress;
|
||||||
Shaders.build.color.set(Pal.accent);
|
Shaders.build.color.set(color);
|
||||||
Shaders.build.color.a = speed;
|
Shaders.build.color.a = speed;
|
||||||
Shaders.build.time = -time / 20f;
|
Shaders.build.time = -time / 20f;
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ public class MinimapRenderer implements Disposable{
|
|||||||
|
|
||||||
Draw.mixcol(unit.team().color, 1f);
|
Draw.mixcol(unit.team().color, 1f);
|
||||||
float scale = Scl.scl(1f) / 2f * scaling * 32f;
|
float scale = Scl.scl(1f) / 2f * scaling * 32f;
|
||||||
Draw.rect(unit.type.icon(Cicon.full), x + rx, y + ry, scale, scale, unit.rotation() - 90);
|
var region = unit.type.icon(Cicon.full);
|
||||||
|
Draw.rect(region, x + rx, y + ry, scale, scale * (float)region.height / region.width, unit.rotation() - 90);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
/** Selected build request for movement. */
|
/** Selected build request for movement. */
|
||||||
public @Nullable BuildPlan sreq;
|
public @Nullable BuildPlan sreq;
|
||||||
/** Whether player is currently deleting removal requests. */
|
/** Whether player is currently deleting removal requests. */
|
||||||
public boolean deleting = false, shouldShoot = false, panning = false;
|
public boolean deleting = false, wasBuilding = true, shouldShoot = false, panning = false;
|
||||||
/** Mouse pan speed. */
|
/** Mouse pan speed. */
|
||||||
public float panScale = 0.005f, panSpeed = 4.5f, panBoostSpeed = 11f;
|
public float panScale = 0.005f, panSpeed = 4.5f, panBoostSpeed = 11f;
|
||||||
|
|
||||||
@@ -62,18 +62,19 @@ public class DesktopInput extends InputHandler{
|
|||||||
group.fill(t -> {
|
group.fill(t -> {
|
||||||
t.bottom();
|
t.bottom();
|
||||||
t.visible(() -> {
|
t.visible(() -> {
|
||||||
t.color.a = Mathf.lerpDelta(t.color.a, player.unit().isBuilding() ? 1f : 0f, 0.15f);
|
t.color.a = Mathf.lerpDelta(t.color.a, !isBuilding && !Core.settings.getBool("buildautopause") || player.unit().isBuilding() ? 1f : 0f, 0.15f);
|
||||||
|
|
||||||
return ui.hudfrag.shown && Core.settings.getBool("hints") && selectRequests.isEmpty() && t.color.a > 0.01f;
|
return ui.hudfrag.shown && Core.settings.getBool("hints") && selectRequests.isEmpty() && t.color.a > 0.01f;
|
||||||
});
|
});
|
||||||
t.touchable(() -> t.color.a < 0.1f ? Touchable.disabled : Touchable.childrenOnly);
|
t.touchable(() -> t.color.a < 0.1f ? Touchable.disabled : Touchable.childrenOnly);
|
||||||
t.table(Styles.black6, b -> {
|
t.table(Styles.black6, b -> {
|
||||||
b.defaults().left();
|
b.defaults().left();
|
||||||
b.label(() -> Core.bundle.format(!isBuilding ? "resumebuilding" : "pausebuilding", Core.keybinds.get(Binding.pause_building).key.toString())).style(Styles.outlineLabel);
|
b.label(() -> ((!isBuilding || !wasBuilding) && !Core.settings.getBool("buildautopause") && !player.unit().isBuilding() ?
|
||||||
b.row();
|
Core.bundle.format("enablebuilding", Core.keybinds.get(Binding.pause_building).key.toString()) :
|
||||||
b.label(() -> Core.bundle.format("cancelbuilding", Core.keybinds.get(Binding.clear_building).key.toString())).style(Styles.outlineLabel);
|
Core.bundle.format(isBuilding ? "pausebuilding" : "resumebuilding", Core.keybinds.get(Binding.pause_building).key.toString()) +
|
||||||
b.row();
|
"\n" + Core.bundle.format("cancelbuilding", Core.keybinds.get(Binding.clear_building).key.toString()) +
|
||||||
b.label(() -> Core.bundle.format("selectschematic", Core.keybinds.get(Binding.schematic_select).key.toString())).style(Styles.outlineLabel);
|
"\n" + Core.bundle.format("selectschematic", Core.keybinds.get(Binding.schematic_select).key.toString())
|
||||||
|
)).style(Styles.outlineLabel);
|
||||||
}).margin(10f);
|
}).margin(10f);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -204,7 +205,6 @@ public class DesktopInput extends InputHandler{
|
|||||||
if(input.keyDown(Binding.mouse_move)){
|
if(input.keyDown(Binding.mouse_move)){
|
||||||
panCam = true;
|
panCam = true;
|
||||||
}
|
}
|
||||||
panning = false;
|
|
||||||
|
|
||||||
Core.camera.position.add(Tmp.v1.setZero().add(Core.input.axis(Binding.move_x), Core.input.axis(Binding.move_y)).nor().scl(camSpeed));
|
Core.camera.position.add(Tmp.v1.setZero().add(Core.input.axis(Binding.move_x), Core.input.axis(Binding.move_y)).nor().scl(camSpeed));
|
||||||
}else if(!player.dead() && !panning){
|
}else if(!player.dead() && !panning){
|
||||||
@@ -455,6 +455,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
buildWasAutoPaused = false;
|
buildWasAutoPaused = false;
|
||||||
|
|
||||||
if(isBuilding){
|
if(isBuilding){
|
||||||
|
wasBuilding = player.unit().isBuilding();
|
||||||
player.shooting = false;
|
player.shooting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,6 +563,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
mode = none;
|
mode = none;
|
||||||
|
wasBuilding = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Core.input.keyTap(Binding.toggle_block_status)){
|
if(Core.input.keyTap(Binding.toggle_block_status)){
|
||||||
|
|||||||
@@ -68,6 +68,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
public Seq<BuildPlan> lineRequests = new Seq<>();
|
public Seq<BuildPlan> lineRequests = new Seq<>();
|
||||||
public Seq<BuildPlan> selectRequests = new Seq<>();
|
public Seq<BuildPlan> selectRequests = new Seq<>();
|
||||||
|
|
||||||
|
public InputHandler(){
|
||||||
|
Events.on(UnitDestroyEvent.class, e -> {
|
||||||
|
if(e.unit != null && e.unit.isPlayer() && e.unit.getPlayer().isLocal() && e.unit.type.weapons.contains(w -> w.bullet.killShooter)){
|
||||||
|
player.shooting = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//methods to override
|
//methods to override
|
||||||
|
|
||||||
@Remote(called = Loc.server, unreliable = true)
|
@Remote(called = Loc.server, unreliable = true)
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ import java.io.*;
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class JsonIO{
|
public class JsonIO{
|
||||||
private static CustomJson jsonBase = new CustomJson();
|
private static final CustomJson jsonBase = new CustomJson();
|
||||||
private static Json json = new Json(){
|
|
||||||
|
public static final Json json = new Json(){
|
||||||
{ apply(this); }
|
{ apply(this); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -39,10 +40,6 @@ public class JsonIO{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Json json(){
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String write(Object object){
|
public static String write(Object object){
|
||||||
return json.toJson(object, object.getClass());
|
return json.toJson(object, object.getClass());
|
||||||
}
|
}
|
||||||
@@ -69,7 +66,6 @@ public class JsonIO{
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void apply(Json json){
|
static void apply(Json json){
|
||||||
json.setIgnoreUnknownFields(true);
|
|
||||||
json.setElementType(Rules.class, "spawns", SpawnGroup.class);
|
json.setElementType(Rules.class, "spawns", SpawnGroup.class);
|
||||||
json.setElementType(Rules.class, "loadout", ItemStack.class);
|
json.setElementType(Rules.class, "loadout", ItemStack.class);
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,13 @@ public enum LAccess{
|
|||||||
maxHealth,
|
maxHealth,
|
||||||
heat,
|
heat,
|
||||||
efficiency,
|
efficiency,
|
||||||
|
timescale,
|
||||||
rotation,
|
rotation,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
shootX,
|
shootX,
|
||||||
shootY,
|
shootY,
|
||||||
|
range,
|
||||||
shooting,
|
shooting,
|
||||||
mineX,
|
mineX,
|
||||||
mineY,
|
mineY,
|
||||||
@@ -44,7 +46,8 @@ public enum LAccess{
|
|||||||
enabled("to"), //"to" is standard for single parameter access
|
enabled("to"), //"to" is standard for single parameter access
|
||||||
shoot("x", "y", "shoot"),
|
shoot("x", "y", "shoot"),
|
||||||
shootp(true, "unit", "shoot"),
|
shootp(true, "unit", "shoot"),
|
||||||
configure(true, 30, "to");
|
configure(true, 30, "to"),
|
||||||
|
color("r", "g", "b");
|
||||||
|
|
||||||
public final String[] params;
|
public final String[] params;
|
||||||
public final boolean isObj;
|
public final boolean isObj;
|
||||||
|
|||||||
@@ -61,9 +61,6 @@ public class LAssembler{
|
|||||||
String[] lines = data.split("\n");
|
String[] lines = data.split("\n");
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(String line : lines){
|
for(String line : lines){
|
||||||
//comments
|
|
||||||
int commentIdx = line.indexOf('#');
|
|
||||||
if(commentIdx != -1) line = line.substring(0, commentIdx).trim();
|
|
||||||
if(line.isEmpty()) continue;
|
if(line.isEmpty()) continue;
|
||||||
//remove trailing semicolons in case someone adds them in for no reason
|
//remove trailing semicolons in case someone adds them in for no reason
|
||||||
if(line.endsWith(";")) line = line.substring(0, line.length() - 1);
|
if(line.endsWith(";")) line = line.substring(0, line.length() - 1);
|
||||||
@@ -74,6 +71,7 @@ public class LAssembler{
|
|||||||
|
|
||||||
try{
|
try{
|
||||||
String[] arr;
|
String[] arr;
|
||||||
|
if(line.startsWith("#")) continue;
|
||||||
|
|
||||||
//yes, I am aware that this can be split with regex, but that's slow and even more incomprehensible
|
//yes, I am aware that this can be split with regex, but that's slow and even more incomprehensible
|
||||||
if(line.contains(" ")){
|
if(line.contains(" ")){
|
||||||
@@ -83,7 +81,9 @@ public class LAssembler{
|
|||||||
|
|
||||||
for(int i = 0; i < line.length() + 1; i++){
|
for(int i = 0; i < line.length() + 1; i++){
|
||||||
char c = i == line.length() ? ' ' : line.charAt(i);
|
char c = i == line.length() ? ' ' : line.charAt(i);
|
||||||
if(c == '"'){
|
if(c == '#' && !inString){
|
||||||
|
break;
|
||||||
|
}else if(c == '"'){
|
||||||
inString = !inString;
|
inString = !inString;
|
||||||
}else if(c == ' ' && !inString){
|
}else if(c == ' ' && !inString){
|
||||||
tokens.add(line.substring(lastIdx, Math.min(i, lastIdx + maxTokenLength)));
|
tokens.add(line.substring(lastIdx, Math.min(i, lastIdx + maxTokenLength)));
|
||||||
@@ -96,6 +96,9 @@ public class LAssembler{
|
|||||||
arr = new String[]{line};
|
arr = new String[]{line};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nothing found
|
||||||
|
if(arr.length == 0) continue;
|
||||||
|
|
||||||
String type = arr[0];
|
String type = arr[0];
|
||||||
|
|
||||||
//legacy stuff
|
//legacy stuff
|
||||||
|
|||||||
@@ -283,13 +283,13 @@ public class LCanvas extends Table{
|
|||||||
t.add().growX();
|
t.add().growX();
|
||||||
|
|
||||||
t.button(Icon.copy, Styles.logici, () -> {
|
t.button(Icon.copy, Styles.logici, () -> {
|
||||||
}).padRight(6).get().tapped(this::copy);
|
}).size(24f).padRight(6).get().tapped(this::copy);
|
||||||
|
|
||||||
t.button(Icon.cancel, Styles.logici, () -> {
|
t.button(Icon.cancel, Styles.logici, () -> {
|
||||||
remove();
|
remove();
|
||||||
dragging = null;
|
dragging = null;
|
||||||
statements.layout();
|
statements.layout();
|
||||||
});
|
}).size(24f);
|
||||||
|
|
||||||
t.addListener(new InputListener(){
|
t.addListener(new InputListener(){
|
||||||
float lastx, lasty;
|
float lastx, lasty;
|
||||||
|
|||||||
@@ -434,7 +434,7 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
case build -> {
|
case build -> {
|
||||||
if(unit.canBuild() && exec.obj(p3) instanceof Block block){
|
if(unit.canBuild() && exec.obj(p3) instanceof Block block){
|
||||||
int x = World.toTile(x1), y = World.toTile(y1);
|
int x = World.toTile(x1 - block.offset/tilesize), y = World.toTile(y1 - block.offset/tilesize);
|
||||||
int rot = exec.numi(p4);
|
int rot = exec.numi(p4);
|
||||||
|
|
||||||
//reset state of last request when necessary
|
//reset state of last request when necessary
|
||||||
@@ -888,6 +888,7 @@ public class LExecutor{
|
|||||||
String strValue =
|
String strValue =
|
||||||
v.objval == null ? "null" :
|
v.objval == null ? "null" :
|
||||||
v.objval instanceof String s ? s :
|
v.objval instanceof String s ? s :
|
||||||
|
v.objval == Blocks.stoneWall ? "solid" : //special alias
|
||||||
v.objval instanceof MappableContent content ? content.name :
|
v.objval instanceof MappableContent content ? content.name :
|
||||||
v.objval instanceof Content ? "[content]" :
|
v.objval instanceof Content ? "[content]" :
|
||||||
v.objval instanceof Building build ? build.block.name :
|
v.objval instanceof Building build ? build.block.name :
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ public class LogicDialog extends BaseDialog{
|
|||||||
p.table(Tex.button, t -> {
|
p.table(Tex.button, t -> {
|
||||||
TextButtonStyle style = Styles.cleart;
|
TextButtonStyle style = Styles.cleart;
|
||||||
t.defaults().size(280f, 60f).left();
|
t.defaults().size(280f, 60f).left();
|
||||||
|
|
||||||
|
t.button("@schematic.copy", Icon.copy, style, () -> {
|
||||||
|
dialog.hide();
|
||||||
|
Core.app.setClipboardText(canvas.save());
|
||||||
|
}).marginLeft(12f);
|
||||||
t.row();
|
t.row();
|
||||||
t.button("@schematic.copy.import", Icon.download, style, () -> {
|
t.button("@schematic.copy.import", Icon.download, style, () -> {
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
@@ -44,11 +49,6 @@ public class LogicDialog extends BaseDialog{
|
|||||||
ui.showException(e);
|
ui.showException(e);
|
||||||
}
|
}
|
||||||
}).marginLeft(12f).disabled(b -> Core.app.getClipboardText() == null);
|
}).marginLeft(12f).disabled(b -> Core.app.getClipboardText() == null);
|
||||||
t.row();
|
|
||||||
t.button("@schematic.copy", Icon.copy, style, () -> {
|
|
||||||
dialog.hide();
|
|
||||||
Core.app.setClipboardText(canvas.save());
|
|
||||||
}).marginLeft(12f);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package mindustry.mod;
|
|||||||
public class ModListing{
|
public class ModListing{
|
||||||
public String repo, name, author, lastUpdated, description, minGameVersion;
|
public String repo, name, author, lastUpdated, description, minGameVersion;
|
||||||
public boolean hasScripts, hasJava;
|
public boolean hasScripts, hasJava;
|
||||||
|
public String[] contentTypes = {};
|
||||||
public int stars;
|
public int stars;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -65,23 +65,39 @@ public class Mods implements Loadable{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the loaded mod found by name, or null if not found. */
|
||||||
|
public @Nullable LoadedMod getMod(String name){
|
||||||
|
return mods.find(m -> m.name.equals(name));
|
||||||
|
}
|
||||||
|
|
||||||
/** @return the loaded mod found by class, or null if not found. */
|
/** @return the loaded mod found by class, or null if not found. */
|
||||||
public @Nullable LoadedMod getMod(Class<? extends Mod> type){
|
public @Nullable LoadedMod getMod(Class<? extends Mod> type){
|
||||||
return mods.find(m -> m.enabled() && m.main != null && m.main.getClass() == type);
|
return mods.find(m -> m.enabled() && m.main != null && m.main.getClass() == type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Imports an external mod file.*/
|
/** Imports an external mod file. Folders are not supported here. */
|
||||||
public void importMod(Fi file) throws IOException{
|
public LoadedMod importMod(Fi file) throws IOException{
|
||||||
Fi dest = modDirectory.child(file.name());
|
String baseName = file.nameWithoutExtension();
|
||||||
if(dest.exists()){
|
String finalName = baseName;
|
||||||
throw new IOException("A file with the same name already exists in the mod folder!");
|
//find a name to prevent any name conflicts
|
||||||
|
int count = 1;
|
||||||
|
while(modDirectory.child(finalName + ".zip").exists()){
|
||||||
|
finalName = baseName + "" + count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fi dest = modDirectory.child(finalName + ".zip");
|
||||||
|
|
||||||
file.copyTo(dest);
|
file.copyTo(dest);
|
||||||
try{
|
try{
|
||||||
mods.add(loadMod(dest));
|
var loaded = loadMod(dest, true);
|
||||||
|
mods.add(loaded);
|
||||||
requiresReload = true;
|
requiresReload = true;
|
||||||
sortMods();
|
sortMods();
|
||||||
|
//try to load the mod's icon so it displays on import
|
||||||
|
Core.app.post(() -> {
|
||||||
|
loadIcon(loaded);
|
||||||
|
});
|
||||||
|
return loaded;
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
dest.delete();
|
dest.delete();
|
||||||
throw e;
|
throw e;
|
||||||
@@ -113,13 +129,18 @@ public class Mods implements Loadable{
|
|||||||
|
|
||||||
private void loadIcons(){
|
private void loadIcons(){
|
||||||
for(LoadedMod mod : mods){
|
for(LoadedMod mod : mods){
|
||||||
//try to load icon for each mod that can have one
|
loadIcon(mod);
|
||||||
if(mod.root.child("icon.png").exists()){
|
}
|
||||||
try{
|
}
|
||||||
mod.iconTexture = new Texture(mod.root.child("icon.png"));
|
|
||||||
}catch(Throwable t){
|
private void loadIcon(LoadedMod mod){
|
||||||
Log.err("Failed to load icon for mod '" + mod.name + "'.", t);
|
//try to load icon for each mod that can have one
|
||||||
}
|
if(mod.root.child("icon.png").exists()){
|
||||||
|
try{
|
||||||
|
mod.iconTexture = new Texture(mod.root.child("icon.png"));
|
||||||
|
mod.iconTexture.setFilter(TextureFilter.linear);
|
||||||
|
}catch(Throwable t){
|
||||||
|
Log.err("Failed to load icon for mod '" + mod.name + "'.", t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,6 +368,7 @@ public class Mods implements Loadable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Events.fire(new FileTreeInitEvent());
|
||||||
|
|
||||||
//add new keys to each bundle
|
//add new keys to each bundle
|
||||||
I18NBundle bundle = Core.bundle;
|
I18NBundle bundle = Core.bundle;
|
||||||
@@ -585,8 +607,14 @@ public class Mods implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Loads a mod file+meta, but does not add it to the list.
|
/** Loads a mod file+meta, but does not add it to the list.
|
||||||
* Note that directories can be loaded as mods.*/
|
* Note that directories can be loaded as mods. */
|
||||||
private LoadedMod loadMod(Fi sourceFile) throws Exception{
|
private LoadedMod loadMod(Fi sourceFile) throws Exception{
|
||||||
|
return loadMod(sourceFile, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Loads a mod file+meta, but does not add it to the list.
|
||||||
|
* Note that directories can be loaded as mods. */
|
||||||
|
private LoadedMod loadMod(Fi sourceFile, boolean overwrite) throws Exception{
|
||||||
Time.mark();
|
Time.mark();
|
||||||
|
|
||||||
ZipFi rootZip = null;
|
ZipFi rootZip = null;
|
||||||
@@ -614,23 +642,47 @@ public class Mods implements Loadable{
|
|||||||
String mainClass = meta.main == null ? camelized.toLowerCase() + "." + camelized + "Mod" : meta.main;
|
String mainClass = meta.main == null ? camelized.toLowerCase() + "." + camelized + "Mod" : meta.main;
|
||||||
String baseName = meta.name.toLowerCase().replace(" ", "-");
|
String baseName = meta.name.toLowerCase().replace(" ", "-");
|
||||||
|
|
||||||
if(mods.contains(m -> m.name.equals(baseName))){
|
var other = mods.find(m -> m.name.equals(baseName));
|
||||||
throw new IllegalArgumentException("A mod with the name '" + baseName + "' is already imported.");
|
|
||||||
|
if(other != null){
|
||||||
|
//steam mods can't really be deleted, they need to be unsubscribed
|
||||||
|
if(overwrite && !other.hasSteamID()){
|
||||||
|
//close zip file
|
||||||
|
if(other.root instanceof ZipFi){
|
||||||
|
other.root.delete();
|
||||||
|
}
|
||||||
|
//delete the old mod directory
|
||||||
|
if(other.file.isDirectory()){
|
||||||
|
other.file.deleteDirectory();
|
||||||
|
}else{
|
||||||
|
other.file.delete();
|
||||||
|
}
|
||||||
|
//unload
|
||||||
|
mods.remove(other);
|
||||||
|
}else{
|
||||||
|
throw new IllegalArgumentException("A mod with the name '" + baseName + "' is already imported.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod mainMod;
|
Mod mainMod;
|
||||||
|
|
||||||
Fi mainFile = zip;
|
Fi mainFile = zip;
|
||||||
String[] path = (mainClass.replace('.', '/') + ".class").split("/");
|
if(android){
|
||||||
for(String str : path){
|
mainFile = mainFile.child("classes.dex");
|
||||||
if(!str.isEmpty()){
|
}else{
|
||||||
mainFile = mainFile.child(str);
|
String[] path = (mainClass.replace('.', '/') + ".class").split("/");
|
||||||
|
for(String str : path){
|
||||||
|
if(!str.isEmpty()){
|
||||||
|
mainFile = mainFile.child(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//make sure the main class exists before loading it; if it doesn't just don't put it there
|
//make sure the main class exists before loading it; if it doesn't just don't put it there
|
||||||
if(mainFile.exists() && Core.settings.getBool("mod-" + baseName + "-enabled", true)){
|
//if the mod is explicitly marked as java, try loading it anyway
|
||||||
//mobile versions don't support class mods
|
if((mainFile.exists() || meta.java) &&
|
||||||
|
Core.settings.getBool("mod-" + baseName + "-enabled", true) && Version.isAtLeast(meta.minGameVersion) && (meta.getMinMajor() >= 105 || headless)){
|
||||||
|
|
||||||
if(ios){
|
if(ios){
|
||||||
throw new IllegalArgumentException("Java class mods are not supported on iOS.");
|
throw new IllegalArgumentException("Java class mods are not supported on iOS.");
|
||||||
}
|
}
|
||||||
@@ -700,6 +752,20 @@ public class Mods implements Loadable{
|
|||||||
this.name = meta.name.toLowerCase().replace(" ", "-");
|
this.name = meta.name.toLowerCase().replace(" ", "-");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return whether this is a java class mod. */
|
||||||
|
public boolean isJava(){
|
||||||
|
return meta.java || main != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getRepo(){
|
||||||
|
return Core.settings.getString("mod-" + name + "-repo", meta.repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepo(String repo){
|
||||||
|
Core.settings.put("mod-" + name + "-repo", repo);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean enabled(){
|
public boolean enabled(){
|
||||||
return state == ModState.enabled || state == ModState.contentErrors;
|
return state == ModState.enabled || state == ModState.contentErrors;
|
||||||
}
|
}
|
||||||
@@ -720,11 +786,7 @@ public class Mods implements Loadable{
|
|||||||
public boolean isSupported(){
|
public boolean isSupported(){
|
||||||
if(isOutdated()) return false;
|
if(isOutdated()) return false;
|
||||||
|
|
||||||
int major = getMinMajor(), minor = getMinMinor();
|
return Version.isAtLeast(meta.minGameVersion);
|
||||||
|
|
||||||
if(Version.build <= 0) return true;
|
|
||||||
|
|
||||||
return Version.build >= major && Version.revision >= minor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return whether this mod is outdated, e.g. not compatible with v6. */
|
/** @return whether this mod is outdated, e.g. not compatible with v6. */
|
||||||
@@ -734,33 +796,7 @@ public class Mods implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getMinMajor(){
|
public int getMinMajor(){
|
||||||
int major = 0;
|
return meta.getMinMajor();
|
||||||
|
|
||||||
String ver = meta.minGameVersion == null ? "0" : meta.minGameVersion;
|
|
||||||
|
|
||||||
if(ver.contains(".")){
|
|
||||||
String[] split = ver.split("\\.");
|
|
||||||
if(split.length == 2){
|
|
||||||
major = Strings.parseInt(split[0], 0);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
major = Strings.parseInt(ver, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return major;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinMinor(){
|
|
||||||
String ver = meta.minGameVersion == null ? "0" : meta.minGameVersion;
|
|
||||||
|
|
||||||
if(ver.contains(".")){
|
|
||||||
String[] split = ver.split("\\.");
|
|
||||||
if(split.length == 2){
|
|
||||||
return Strings.parseInt(split[1], 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -842,6 +878,8 @@ public class Mods implements Loadable{
|
|||||||
public Seq<String> dependencies = Seq.with();
|
public Seq<String> dependencies = Seq.with();
|
||||||
/** Hidden mods are only server-side or client-side, and do not support adding new content. */
|
/** Hidden mods are only server-side or client-side, and do not support adding new content. */
|
||||||
public boolean hidden;
|
public boolean hidden;
|
||||||
|
/** If true, this mod should be loaded as a Java class mod. This is technically optional, but highly recommended. */
|
||||||
|
public boolean java;
|
||||||
|
|
||||||
public String displayName(){
|
public String displayName(){
|
||||||
return displayName == null ? name : displayName;
|
return displayName == null ? name : displayName;
|
||||||
@@ -854,6 +892,12 @@ public class Mods implements Loadable{
|
|||||||
if(description != null) description = Strings.stripColors(description);
|
if(description != null) description = Strings.stripColors(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMinMajor(){
|
||||||
|
String ver = minGameVersion == null ? "0" : minGameVersion;
|
||||||
|
int dot = ver.indexOf(".");
|
||||||
|
return dot != -1 ? Strings.parseInt(ver.substring(0, dot), 0) : Strings.parseInt(ver, 0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ModMeta{" +
|
return "ModMeta{" +
|
||||||
@@ -863,6 +907,7 @@ public class Mods implements Loadable{
|
|||||||
", main='" + main + '\'' +
|
", main='" + main + '\'' +
|
||||||
", minGameVersion='" + minGameVersion + '\'' +
|
", minGameVersion='" + minGameVersion + '\'' +
|
||||||
", hidden=" + hidden +
|
", hidden=" + hidden +
|
||||||
|
", repo=" + repo +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class Scripts implements Disposable{
|
|||||||
public String runConsole(String text){
|
public String runConsole(String text){
|
||||||
try{
|
try{
|
||||||
Object o = context.evaluateString(scope, text, "console.js", 1, null);
|
Object o = context.evaluateString(scope, text, "console.js", 1, null);
|
||||||
if(o instanceof NativeJavaObject) o = ((NativeJavaObject)o).unwrap();
|
if(o instanceof NativeJavaObject n) o = n.unwrap();
|
||||||
if(o instanceof Undefined) o = "undefined";
|
if(o instanceof Undefined) o = "undefined";
|
||||||
return String.valueOf(o);
|
return String.valueOf(o);
|
||||||
}catch(Throwable t){
|
}catch(Throwable t){
|
||||||
|
|||||||
@@ -274,9 +274,7 @@ public class Net{
|
|||||||
public void handleServerReceived(NetConnection connection, Object object){
|
public void handleServerReceived(NetConnection connection, Object object){
|
||||||
|
|
||||||
if(serverListeners.get(object.getClass()) != null){
|
if(serverListeners.get(object.getClass()) != null){
|
||||||
if(serverListeners.get(object.getClass()) != null){
|
serverListeners.get(object.getClass()).get(connection, object);
|
||||||
serverListeners.get(object.getClass()).get(connection, object);
|
|
||||||
}
|
|
||||||
Pools.free(object);
|
Pools.free(object);
|
||||||
}else{
|
}else{
|
||||||
Log.err("Unhandled packet type: '@'!", object.getClass());
|
Log.err("Unhandled packet type: '@'!", object.getClass());
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ public class Item extends UnlockableContent{
|
|||||||
public float flammability = 0f;
|
public float flammability = 0f;
|
||||||
/** how radioactive this item is. 0=none, 1=chernobyl ground zero */
|
/** how radioactive this item is. 0=none, 1=chernobyl ground zero */
|
||||||
public float radioactivity;
|
public float radioactivity;
|
||||||
|
/** how electrically potent this item is. */
|
||||||
|
public float charge = 0f;
|
||||||
/** drill hardness of the item */
|
/** drill hardness of the item */
|
||||||
public int hardness = 0;
|
public int hardness = 0;
|
||||||
/**
|
/**
|
||||||
@@ -41,6 +43,7 @@ public class Item extends UnlockableContent{
|
|||||||
stats.addPercent(Stat.explosiveness, explosiveness);
|
stats.addPercent(Stat.explosiveness, explosiveness);
|
||||||
stats.addPercent(Stat.flammability, flammability);
|
stats.addPercent(Stat.flammability, flammability);
|
||||||
stats.addPercent(Stat.radioactivity, radioactivity);
|
stats.addPercent(Stat.radioactivity, radioactivity);
|
||||||
|
stats.addPercent(Stat.charge, charge);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public class StatusEffect extends MappableContent{
|
|||||||
public float effectChance = 0.15f;
|
public float effectChance = 0.15f;
|
||||||
/** If true, the effect never disappears. */
|
/** If true, the effect never disappears. */
|
||||||
public boolean permanent;
|
public boolean permanent;
|
||||||
|
/** If true, this effect will only react with other effects and cannot be applied. */
|
||||||
|
public boolean reactive;
|
||||||
/** Tint color of effect. */
|
/** Tint color of effect. */
|
||||||
public Color color = Color.white.cpy();
|
public Color color = Color.white.cpy();
|
||||||
/** Effect that happens randomly on top of the affected unit. */
|
/** Effect that happens randomly on top of the affected unit. */
|
||||||
@@ -63,6 +65,7 @@ public class StatusEffect extends MappableContent{
|
|||||||
|
|
||||||
protected void trans(StatusEffect effect, TransitionHandler handler){
|
protected void trans(StatusEffect effect, TransitionHandler handler){
|
||||||
transitions.put(effect, handler);
|
transitions.put(effect, handler);
|
||||||
|
effect.transitions.put(this, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void opposite(StatusEffect... effect){
|
protected void opposite(StatusEffect... effect){
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ 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.ai.types.*;
|
import mindustry.ai.types.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
@@ -224,6 +225,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
Unit inst = constructor.get();
|
Unit inst = constructor.get();
|
||||||
|
|
||||||
stats.add(Stat.health, health);
|
stats.add(Stat.health, health);
|
||||||
|
stats.add(Stat.armor, armor);
|
||||||
stats.add(Stat.speed, speed);
|
stats.add(Stat.speed, speed);
|
||||||
stats.add(Stat.itemCapacity, itemCapacity);
|
stats.add(Stat.itemCapacity, itemCapacity);
|
||||||
stats.add(Stat.range, (int)(maxRange / tilesize), StatUnit.blocks);
|
stats.add(Stat.range, (int)(maxRange / tilesize), StatUnit.blocks);
|
||||||
@@ -292,12 +294,17 @@ public class UnitType extends UnlockableContent{
|
|||||||
|
|
||||||
if(maxRange < 0){
|
if(maxRange < 0){
|
||||||
maxRange = 0f;
|
maxRange = 0f;
|
||||||
|
maxRange = Math.max(maxRange, range);
|
||||||
|
|
||||||
for(Weapon weapon : weapons){
|
for(Weapon weapon : weapons){
|
||||||
maxRange = Math.max(maxRange, weapon.bullet.range() + hitSize / 2f);
|
maxRange = Math.max(maxRange, weapon.bullet.range() + hitSize / 2f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(weapons.isEmpty()){
|
||||||
|
range = maxRange = miningRange;
|
||||||
|
}
|
||||||
|
|
||||||
if(mechStride < 0){
|
if(mechStride < 0){
|
||||||
mechStride = 4f + (hitSize -8f)/2.1f;
|
mechStride = 4f + (hitSize -8f)/2.1f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import arc.scene.ui.layout.*;
|
|||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
|
||||||
public class BorderImage extends Image{
|
public class BorderImage extends Image{
|
||||||
public float thickness = 4f;
|
public float thickness = 4f, pad = 0f;
|
||||||
public Color borderColor = Pal.gray;
|
public Color borderColor = Pal.gray;
|
||||||
|
|
||||||
public BorderImage(){
|
public BorderImage(){
|
||||||
@@ -40,7 +40,7 @@ public class BorderImage extends Image{
|
|||||||
Draw.color(borderColor);
|
Draw.color(borderColor);
|
||||||
Draw.alpha(parentAlpha);
|
Draw.alpha(parentAlpha);
|
||||||
Lines.stroke(Scl.scl(thickness));
|
Lines.stroke(Scl.scl(thickness));
|
||||||
Lines.rect(x + imageX, y + imageY, imageWidth * scaleX, imageHeight * scaleY);
|
Lines.rect(x + imageX - pad, y + imageY - pad, imageWidth * scaleX + pad*2, imageHeight * scaleY + pad*2);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ public class CustomGameDialog extends BaseDialog{
|
|||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
clearChildren();
|
clearChildren();
|
||||||
add(titleTable);
|
add(titleTable).growX().row();
|
||||||
row();
|
|
||||||
stack(cont, buttons).grow();
|
stack(cont, buttons).grow();
|
||||||
buttons.bottom();
|
buttons.bottom();
|
||||||
cont.clear();
|
cont.clear();
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
|
|
||||||
title("@rules.title.unit");
|
title("@rules.title.unit");
|
||||||
check("@rules.unitammo", b -> rules.unitAmmo = b, () -> rules.unitAmmo);
|
check("@rules.unitammo", b -> rules.unitAmmo = b, () -> rules.unitAmmo);
|
||||||
number("@rules.unithealthmultiplier", f -> rules.unitHealthMultiplier = f, () -> rules.unitHealthMultiplier);
|
|
||||||
number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier);
|
number("@rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier);
|
||||||
number("@rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier, 0.001f, 50f);
|
number("@rules.unitbuildspeedmultiplier", f -> rules.unitBuildSpeedMultiplier = f, () -> rules.unitBuildSpeedMultiplier, 0.001f, 50f);
|
||||||
|
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ public class DatabaseDialog extends BaseDialog{
|
|||||||
list.add(image).size(8 * 4).pad(3);
|
list.add(image).size(8 * 4).pad(3);
|
||||||
ClickListener listener = new ClickListener();
|
ClickListener listener = new ClickListener();
|
||||||
image.addListener(listener);
|
image.addListener(listener);
|
||||||
if(!Vars.mobile && unlocked(unlock)){
|
if(!mobile && unlocked(unlock)){
|
||||||
image.addListener(new HandCursorListener());
|
image.addListener(new HandCursorListener());
|
||||||
image.update(() -> image.color.lerp(!listener.isOver() ? Color.lightGray : Color.white, 0.4f * Time.delta));
|
image.update(() -> image.color.lerp(!listener.isOver() ? Color.lightGray : Color.white, Mathf.clamp(0.4f * Time.delta)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unlocked(unlock)){
|
if(unlocked(unlock)){
|
||||||
@@ -71,7 +71,7 @@ public class DatabaseDialog extends BaseDialog{
|
|||||||
Core.app.setClipboardText((char)Fonts.getUnicode(unlock.name) + "");
|
Core.app.setClipboardText((char)Fonts.getUnicode(unlock.name) + "");
|
||||||
ui.showInfoFade("@copied");
|
ui.showInfoFade("@copied");
|
||||||
}else{
|
}else{
|
||||||
Vars.ui.content.show(unlock);
|
ui.content.show(unlock);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
image.addListener(new Tooltip(t -> t.background(Tex.button).add(unlock.localizedName)));
|
image.addListener(new Tooltip(t -> t.background(Tex.button).add(unlock.localizedName)));
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import arc.func.*;
|
|||||||
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 mindustry.content.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -105,6 +106,7 @@ public class LaunchLoadoutDialog extends BaseDialog{
|
|||||||
int cols = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1);
|
int cols = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1);
|
||||||
ButtonGroup<Button> group = new ButtonGroup<>();
|
ButtonGroup<Button> group = new ButtonGroup<>();
|
||||||
selected = universe.getLoadout(core);
|
selected = universe.getLoadout(core);
|
||||||
|
if(selected == null) selected = schematics.getLoadouts().get((CoreBlock)Blocks.coreShard).first();
|
||||||
|
|
||||||
cont.add(Core.bundle.format("launch.from", sector.name())).row();
|
cont.add(Core.bundle.format("launch.from", sector.name())).row();
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class MapPlayDialog extends BaseDialog{
|
|||||||
|
|
||||||
cont.add(selmode);
|
cont.add(selmode);
|
||||||
cont.row();
|
cont.row();
|
||||||
cont.button("@customize", Icon.settings, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).width(230);
|
cont.button("@customize", Icon.settings, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).height(50f).width(230);
|
||||||
cont.row();
|
cont.row();
|
||||||
cont.add(new BorderImage(map.safeTexture(), 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit);
|
cont.add(new BorderImage(map.safeTexture(), 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit);
|
||||||
//only maps with survival are valid for high scores
|
//only maps with survival are valid for high scores
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import arc.Net.*;
|
|||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
|
import arc.graphics.Texture.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.input.*;
|
import arc.input.*;
|
||||||
import arc.scene.style.*;
|
import arc.scene.style.*;
|
||||||
import arc.scene.ui.TextButton.*;
|
import arc.scene.ui.TextButton.*;
|
||||||
|
import arc.scene.ui.*;
|
||||||
|
import arc.scene.ui.layout.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
@@ -16,8 +19,10 @@ import arc.util.serialization.*;
|
|||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.core.*;
|
import mindustry.core.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.io.*;
|
||||||
import mindustry.mod.*;
|
import mindustry.mod.*;
|
||||||
import mindustry.mod.Mods.*;
|
import mindustry.mod.Mods.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
@@ -29,20 +34,72 @@ import java.util.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class ModsDialog extends BaseDialog{
|
public class ModsDialog extends BaseDialog{
|
||||||
|
private ObjectMap<String, TextureRegion> textureCache = new ObjectMap<>();
|
||||||
|
|
||||||
private String searchtxt = "";
|
private String searchtxt = "";
|
||||||
private @Nullable Seq<ModListing> modList;
|
private @Nullable Seq<ModListing> modList;
|
||||||
|
private boolean orderDate = true;
|
||||||
|
private BaseDialog currentContent;
|
||||||
|
|
||||||
|
private BaseDialog browser;
|
||||||
|
private Table browserTable;
|
||||||
|
|
||||||
public ModsDialog(){
|
public ModsDialog(){
|
||||||
super("@mods");
|
super("@mods");
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
|
|
||||||
|
Events.on(DisposeEvent.class, e -> {
|
||||||
|
textureCache.each((key, val) -> {
|
||||||
|
if(val.texture.width == val.width){
|
||||||
|
val.texture.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
textureCache.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
browser = new BaseDialog("@mods.browser");
|
||||||
|
|
||||||
|
browser.cont.table(table -> {
|
||||||
|
table.left();
|
||||||
|
table.image(Icon.zoom);
|
||||||
|
table.field(searchtxt, res -> {
|
||||||
|
searchtxt = res;
|
||||||
|
rebuildBrowser();
|
||||||
|
}).growX().get();
|
||||||
|
table.button(Icon.list, Styles.clearPartiali, 32f, () -> {
|
||||||
|
orderDate = !orderDate;
|
||||||
|
rebuildBrowser();
|
||||||
|
}).update(b -> b.getStyle().imageUp = (orderDate ? Icon.list : Icon.star)).size(40f).get()
|
||||||
|
.addListener(new Tooltip(tip -> tip.label(() -> orderDate ? "@mods.browser.sortdate" : "@mods.browser.sortstars").left()));
|
||||||
|
}).fillX().padBottom(4);
|
||||||
|
|
||||||
|
browser.cont.row();
|
||||||
|
browser.cont.pane(tablebrow -> {
|
||||||
|
tablebrow.margin(10f).top();
|
||||||
|
browserTable = tablebrow;
|
||||||
|
}).get().setScrollingDisabled(true, false);
|
||||||
|
browser.addCloseButton();
|
||||||
|
|
||||||
|
browser.onResize(this::rebuildBrowser);
|
||||||
|
|
||||||
buttons.button("@mods.guide", Icon.link, () -> Core.app.openURI(modGuideURL)).size(210, 64f);
|
buttons.button("@mods.guide", Icon.link, () -> Core.app.openURI(modGuideURL)).size(210, 64f);
|
||||||
|
|
||||||
|
if(!mobile){
|
||||||
|
buttons.button("@mods.openfolder", Icon.link, () -> Core.app.openFolder(modDirectory.absolutePath()));
|
||||||
|
}
|
||||||
|
|
||||||
shown(this::setup);
|
shown(this::setup);
|
||||||
if(mobile){
|
if(mobile){
|
||||||
onResize(this::setup);
|
onResize(this::setup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Events.on(ResizeEvent.class, event -> {
|
||||||
|
if(currentContent != null){
|
||||||
|
currentContent.hide();
|
||||||
|
currentContent = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
hidden(() -> {
|
hidden(() -> {
|
||||||
if(mods.requiresReload()){
|
if(mods.requiresReload()){
|
||||||
reload();
|
reload();
|
||||||
@@ -77,7 +134,7 @@ public class ModsDialog extends BaseDialog{
|
|||||||
ui.showErrorMessage(Core.bundle.format("connectfail", status));
|
ui.showErrorMessage(Core.bundle.format("connectfail", status));
|
||||||
}else{
|
}else{
|
||||||
try{
|
try{
|
||||||
modList = new Json().fromJson(Seq.class, ModListing.class, strResult);
|
modList = JsonIO.json.fromJson(Seq.class, ModListing.class, strResult);
|
||||||
|
|
||||||
var d = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
var d = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||||
Func<String, Date> parser = text -> {
|
Func<String, Date> parser = text -> {
|
||||||
@@ -97,7 +154,7 @@ public class ModsDialog extends BaseDialog{
|
|||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, error -> Core.app.post(() -> ui.showException(error)));
|
}, error -> Core.app.post(() -> modError(error)));
|
||||||
}else{
|
}else{
|
||||||
listener.get(modList);
|
listener.get(modList);
|
||||||
}
|
}
|
||||||
@@ -156,81 +213,15 @@ public class ModsDialog extends BaseDialog{
|
|||||||
dialog.hide();
|
dialog.hide();
|
||||||
|
|
||||||
ui.showTextInput("@mod.import.github", "", 64, Core.settings.getString("lastmod", ""), text -> {
|
ui.showTextInput("@mod.import.github", "", 64, Core.settings.getString("lastmod", ""), text -> {
|
||||||
|
//clean up the text in case somebody inputs a URL or adds random spaces
|
||||||
|
text = text.trim().replace(" ", "");
|
||||||
|
if(text.startsWith("https://github.com/")) text = text.substring("https://github.com/".length());
|
||||||
|
|
||||||
Core.settings.put("lastmod", text);
|
Core.settings.put("lastmod", text);
|
||||||
|
//there's no good way to know if it's a java mod here, so assume it's not
|
||||||
ui.loadfrag.show();
|
githubImportMod(text, false);
|
||||||
githubImportMod(text);
|
|
||||||
});
|
});
|
||||||
}).margin(12f);
|
}).margin(12f);
|
||||||
|
|
||||||
t.row();
|
|
||||||
|
|
||||||
t.button("@mod.featured.dialog.title", Icon.star, bstyle, () -> {
|
|
||||||
Runnable[] rebuildBrowser = {null};
|
|
||||||
dialog.hide();
|
|
||||||
BaseDialog browser = new BaseDialog("$mod.featured.dialog.title");
|
|
||||||
browser.cont.table(table -> {
|
|
||||||
table.left();
|
|
||||||
table.image(Icon.zoom);
|
|
||||||
table.field(searchtxt, res -> {
|
|
||||||
searchtxt = res;
|
|
||||||
rebuildBrowser[0].run();
|
|
||||||
}).growX().get();
|
|
||||||
}).fillX().padBottom(4);
|
|
||||||
|
|
||||||
browser.cont.row();
|
|
||||||
|
|
||||||
browser.cont.pane(tablebrow -> {
|
|
||||||
tablebrow.margin(10f).top();
|
|
||||||
rebuildBrowser[0] = () -> {
|
|
||||||
tablebrow.clear();
|
|
||||||
tablebrow.add("@loading");
|
|
||||||
|
|
||||||
getModList(listings -> {
|
|
||||||
tablebrow.clear();
|
|
||||||
|
|
||||||
for(ModListing mod : listings){
|
|
||||||
if(mod.hasJava || !searchtxt.isEmpty() && !mod.repo.toLowerCase().contains(searchtxt.toLowerCase()) || (Vars.ios && mod.hasScripts)) continue;
|
|
||||||
|
|
||||||
tablebrow.button(btn -> {
|
|
||||||
btn.top().left();
|
|
||||||
btn.margin(12f);
|
|
||||||
btn.table(con -> {
|
|
||||||
con.left();
|
|
||||||
con.add("[accent]" + mod.name + "[white]\n[lightgray]Author:[] " + mod.author + "\n[lightgray]\uE809 " + mod.stars +
|
|
||||||
(Version.isAtLeast(mod.minGameVersion) ? "" : "\n" + Core.bundle.format("mod.requiresversion", mod.minGameVersion)))
|
|
||||||
.width(388f).wrap().growX().pad(0f, 6f, 0f, 6f).left().labelAlign(Align.left);
|
|
||||||
con.add().growX().pad(0f, 6f, 0f, 6f);
|
|
||||||
}).fillY().growX().pad(0f, 6f, 0f, 6f);
|
|
||||||
}, Styles.modsb, () -> {
|
|
||||||
var sel = new BaseDialog(mod.name);
|
|
||||||
sel.cont.add(mod.description).width(mobile ? 400f : 500f).wrap().pad(4f).labelAlign(Align.center, Align.left);
|
|
||||||
sel.buttons.defaults().size(150f, 54f).pad(2f);
|
|
||||||
sel.setFillParent(false);
|
|
||||||
sel.buttons.button("@back", Icon.left, () -> {
|
|
||||||
sel.clear();
|
|
||||||
sel.hide();
|
|
||||||
});
|
|
||||||
sel.buttons.button("@mods.browser.add", Icon.download, () -> {
|
|
||||||
sel.hide();
|
|
||||||
githubImportMod(mod.repo);
|
|
||||||
});
|
|
||||||
sel.buttons.button("@mods.github.open", Icon.link, () -> {
|
|
||||||
Core.app.openURI("https://github.com/" + mod.repo);
|
|
||||||
});
|
|
||||||
sel.keyDown(KeyCode.escape, sel::hide);
|
|
||||||
sel.keyDown(KeyCode.back, sel::hide);
|
|
||||||
sel.show();
|
|
||||||
}).width(480f).growX().left().fillY();
|
|
||||||
tablebrow.row();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
rebuildBrowser[0].run();
|
|
||||||
});
|
|
||||||
browser.addCloseButton();
|
|
||||||
browser.show();
|
|
||||||
}).margin(12f);
|
|
||||||
});
|
});
|
||||||
dialog.addCloseButton();
|
dialog.addCloseButton();
|
||||||
|
|
||||||
@@ -238,9 +229,7 @@ public class ModsDialog extends BaseDialog{
|
|||||||
|
|
||||||
}).margin(margin);
|
}).margin(margin);
|
||||||
|
|
||||||
if(!mobile){
|
buttons.button("@mods.browser", Icon.menu, style, this::showModBrowser).margin(margin);
|
||||||
buttons.button("@mods.openfolder", Icon.link, style, () -> Core.app.openFolder(modDirectory.absolutePath())).margin(margin);
|
|
||||||
}
|
|
||||||
}).width(w);
|
}).width(w);
|
||||||
|
|
||||||
cont.row();
|
cont.row();
|
||||||
@@ -277,7 +266,7 @@ public class ModsDialog extends BaseDialog{
|
|||||||
title.table(text -> {
|
title.table(text -> {
|
||||||
boolean hideDisabled = !mod.isSupported() || mod.hasUnmetDependencies() || mod.hasContentErrors();
|
boolean hideDisabled = !mod.isSupported() || mod.hasUnmetDependencies() || mod.hasContentErrors();
|
||||||
|
|
||||||
text.add("" + mod.meta.displayName() + "\n[lightgray]v" + mod.meta.version + (mod.enabled() || hideDisabled ? "" : "\n" + Core.bundle.get("mod.disabled") + ""))
|
text.add("" + Strings.stripColors(mod.meta.displayName()) + "\n[lightgray]v" + Strings.stripColors(trimText(mod.meta.version)) + (mod.enabled() || hideDisabled ? "" : "\n" + Core.bundle.get("mod.disabled") + ""))
|
||||||
.wrap().top().width(300f).growX().left();
|
.wrap().top().width(300f).growX().left();
|
||||||
|
|
||||||
text.row();
|
text.row();
|
||||||
@@ -336,7 +325,7 @@ public class ModsDialog extends BaseDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reload(){
|
private void reload(){
|
||||||
ui.showInfo("@mods.reloadexit", () -> Core.app.exit());
|
ui.showInfoOnHidden("@mods.reloadexit", () -> Core.app.exit());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMod(LoadedMod mod){
|
private void showMod(LoadedMod mod){
|
||||||
@@ -348,6 +337,13 @@ public class ModsDialog extends BaseDialog{
|
|||||||
dialog.buttons.button("@mods.openfolder", Icon.link, () -> Core.app.openFolder(mod.file.absolutePath()));
|
dialog.buttons.button("@mods.openfolder", Icon.link, () -> Core.app.openFolder(mod.file.absolutePath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mod.getRepo() != null){
|
||||||
|
boolean showImport = !mod.hasSteamID();
|
||||||
|
dialog.buttons.button("@mods.github.open", Icon.link, () -> Core.app.openURI("https://github.com/" + mod.getRepo()));
|
||||||
|
if(mobile && showImport) dialog.buttons.row();
|
||||||
|
if(showImport) dialog.buttons.button("@mods.browser.reinstall", Icon.download, () -> githubImportMod(mod.getRepo(), mod.isJava()));
|
||||||
|
}
|
||||||
|
|
||||||
//TODO improve this menu later
|
//TODO improve this menu later
|
||||||
dialog.cont.pane(desc -> {
|
dialog.cont.pane(desc -> {
|
||||||
desc.center();
|
desc.center();
|
||||||
@@ -372,12 +368,12 @@ public class ModsDialog extends BaseDialog{
|
|||||||
|
|
||||||
}).width(400f);
|
}).width(400f);
|
||||||
|
|
||||||
//TODO maybe enable later
|
Seq<UnlockableContent> all = Seq.with(content.getContentMap()).<Content>flatten().select(c -> c.minfo.mod == mod && c instanceof UnlockableContent).as();
|
||||||
if(false){
|
if(all.any()){
|
||||||
Seq<UnlockableContent> all = Seq.with(content.getContentMap()).<Content>flatten().select(c -> c.minfo.mod == mod && c instanceof UnlockableContent).as();
|
dialog.cont.row();
|
||||||
if(all.any()){
|
dialog.cont.button( "@mods.viewcontent", Icon.book, () -> {
|
||||||
dialog.cont.row();
|
BaseDialog d = new BaseDialog(mod.meta.displayName());
|
||||||
dialog.cont.pane(cs -> {
|
d.cont.pane(cs -> {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(UnlockableContent c : all){
|
for(UnlockableContent c : all){
|
||||||
cs.button(new TextureRegionDrawable(c.icon(Cicon.medium)), Styles.cleari, Cicon.medium.size, () -> {
|
cs.button(new TextureRegionDrawable(c.icon(Cicon.medium)), Styles.cleari, Cicon.medium.size, () -> {
|
||||||
@@ -385,24 +381,145 @@ public class ModsDialog extends BaseDialog{
|
|||||||
}).size(50f).with(im -> {
|
}).size(50f).with(im -> {
|
||||||
var click = im.getClickListener();
|
var click = im.getClickListener();
|
||||||
im.update(() -> im.getImage().color.lerp(!click.isOver() ? Color.lightGray : Color.white, 0.4f * Time.delta));
|
im.update(() -> im.getImage().color.lerp(!click.isOver() ? Color.lightGray : Color.white, 0.4f * Time.delta));
|
||||||
});
|
|
||||||
|
|
||||||
if(++i % 8 == 0) cs.row();
|
}).tooltip(c.localizedName);
|
||||||
|
|
||||||
|
if(++i % Math.min(Core.graphics.getWidth() / Scl.scl(70), 14) == 0) cs.row();
|
||||||
}
|
}
|
||||||
}).growX().minHeight(60f);
|
}).grow();
|
||||||
}
|
d.addCloseButton();
|
||||||
|
d.show();
|
||||||
|
currentContent = d;
|
||||||
|
}).size(300, 50).pad(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showModBrowser(){
|
||||||
|
rebuildBrowser();
|
||||||
|
browser.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rebuildBrowser(){
|
||||||
|
ObjectSet<String> installed = mods.list().map(m -> m.getRepo()).asSet();
|
||||||
|
|
||||||
|
browserTable.clear();
|
||||||
|
browserTable.add("@loading");
|
||||||
|
|
||||||
|
int cols = (int)Math.max(Core.graphics.getWidth() / Scl.scl(480), 1);
|
||||||
|
|
||||||
|
getModList(rlistings -> {
|
||||||
|
browserTable.clear();
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
Seq<ModListing> listings = rlistings;
|
||||||
|
if(!orderDate){
|
||||||
|
listings = rlistings.copy();
|
||||||
|
listings.sortComparing(m1 -> -m1.stars);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(ModListing mod : listings){
|
||||||
|
if((mod.hasJava && Vars.ios) || !searchtxt.isEmpty() && !mod.repo.toLowerCase().contains(searchtxt.toLowerCase()) || (Vars.ios && mod.hasScripts)) continue;
|
||||||
|
|
||||||
|
float s = 64f;
|
||||||
|
|
||||||
|
browserTable.button(con -> {
|
||||||
|
con.margin(0f);
|
||||||
|
con.left();
|
||||||
|
|
||||||
|
String repo = mod.repo;
|
||||||
|
con.add(new BorderImage(){
|
||||||
|
TextureRegion last;
|
||||||
|
|
||||||
|
{
|
||||||
|
border(installed.contains(repo) ? Pal.accent : Color.lightGray);
|
||||||
|
setDrawable(Tex.nomap);
|
||||||
|
pad = Scl.scl(4f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
super.draw();
|
||||||
|
|
||||||
|
//textures are only requested when the rendering happens; this assists with culling
|
||||||
|
if(!textureCache.containsKey(repo)){
|
||||||
|
textureCache.put(repo, last = Tex.nomap.getRegion());
|
||||||
|
Core.net.httpGet("https://raw.githubusercontent.com/Anuken/MindustryMods/master/icons/" + repo.replace("/", "_"), res -> {
|
||||||
|
if(res.getStatus() == HttpStatus.OK){
|
||||||
|
Pixmap pix = new Pixmap(res.getResult());
|
||||||
|
Core.app.post(() -> {
|
||||||
|
try{
|
||||||
|
var tex = new Texture(pix);
|
||||||
|
tex.setFilter(TextureFilter.linear);
|
||||||
|
textureCache.put(repo, new TextureRegion(tex));
|
||||||
|
pix.dispose();
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.err(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, err -> {});
|
||||||
|
}
|
||||||
|
|
||||||
|
var next = textureCache.get(repo);
|
||||||
|
if(last != next){
|
||||||
|
last = next;
|
||||||
|
setDrawable(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).size(s).pad(4f * 2f);
|
||||||
|
|
||||||
|
con.add(
|
||||||
|
"[accent]" + mod.name.replace("\n", "") +
|
||||||
|
(installed.contains(mod.repo) ? "\n[lightgray]" + Core.bundle.get("mod.installed") : "") +
|
||||||
|
//"[white]\n[lightgray]Author:[] " + trimText(mod.author) +
|
||||||
|
"\n[lightgray]\uE809 " + mod.stars +
|
||||||
|
(Version.isAtLeast(mod.minGameVersion) ? "" : "\n" + Core.bundle.format("mod.requiresversion", mod.minGameVersion)))
|
||||||
|
.width(358f).wrap().grow().pad(4f, 2f, 4f, 6f).top().left().labelAlign(Align.topLeft);
|
||||||
|
|
||||||
|
}, Styles.clearPartialt, () -> {
|
||||||
|
var sel = new BaseDialog(mod.name);
|
||||||
|
sel.cont.pane(p -> p.add(mod.description + "\n\n[accent]" + Core.bundle.get("editor.author") + "[lightgray] " + mod.author)
|
||||||
|
.width(mobile ? 400f : 500f).wrap().pad(4f).labelAlign(Align.center, Align.left)).grow();
|
||||||
|
sel.buttons.defaults().size(150f, 54f).pad(2f);
|
||||||
|
sel.buttons.button("@back", Icon.left, () -> {
|
||||||
|
sel.clear();
|
||||||
|
sel.hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
var found = mods.list().find(l -> mod.repo != null && mod.repo.equals(l.getRepo()));
|
||||||
|
sel.buttons.button(found == null ? "@mods.browser.add" : "@mods.browser.reinstall", Icon.download, () -> {
|
||||||
|
sel.hide();
|
||||||
|
githubImportMod(mod.repo, mod.hasJava);
|
||||||
|
});
|
||||||
|
sel.buttons.button("@mods.github.open", Icon.link, () -> {
|
||||||
|
Core.app.openURI("https://github.com/" + mod.repo);
|
||||||
|
});
|
||||||
|
sel.keyDown(KeyCode.escape, sel::hide);
|
||||||
|
sel.keyDown(KeyCode.back, sel::hide);
|
||||||
|
sel.show();
|
||||||
|
}).width(438f).pad(4).growX().left().height(s + 8*2f).fillY();
|
||||||
|
|
||||||
|
if(++i % cols == 0) browserTable.row();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimText(String text){
|
||||||
|
if(text == null) return "";
|
||||||
|
if(text.contains("\n")){
|
||||||
|
return text.substring(0, text.indexOf("\n"));
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
private void handleMod(String repo, HttpResponse result){
|
private void handleMod(String repo, HttpResponse result){
|
||||||
try{
|
try{
|
||||||
Fi file = tmpDirectory.child(repo.replace("/", "") + ".zip");
|
Fi file = tmpDirectory.child(repo.replace("/", "") + ".zip");
|
||||||
Streams.copy(result.getResultAsStream(), file.write(false));
|
Streams.copy(result.getResultAsStream(), file.write(false));
|
||||||
mods.importMod(file);
|
var mod = mods.importMod(file);
|
||||||
|
mod.setRepo(repo);
|
||||||
file.delete();
|
file.delete();
|
||||||
Core.app.post(() -> {
|
Core.app.post(() -> {
|
||||||
try{
|
try{
|
||||||
@@ -417,21 +534,80 @@ public class ModsDialog extends BaseDialog{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void githubImportMod(String name){
|
private void importFail(Throwable t){
|
||||||
//try several branches
|
Core.app.post(() -> modError(t));
|
||||||
//TODO use only the main branch as specified in meta
|
}
|
||||||
githubImportBranch("6.0", name, e1 -> {
|
|
||||||
githubImportBranch("master", name, e2 -> {
|
private void githubImportMod(String repo, boolean isJava){
|
||||||
githubImportBranch("main", name, e3 -> {
|
if(isJava){
|
||||||
ui.showErrorMessage(Core.bundle.format("connectfail", e2));
|
ui.showConfirm("@warning", "@mod.jarwarn", () -> {
|
||||||
ui.loadfrag.hide();
|
ui.loadfrag.show();
|
||||||
});
|
githubImportJavaMod(repo);
|
||||||
});
|
});
|
||||||
|
}else{
|
||||||
|
ui.loadfrag.show();
|
||||||
|
Core.net.httpGet(ghApi + "/repos/" + repo, res -> {
|
||||||
|
if(checkError(res)){
|
||||||
|
var json = Jval.read(res.getResultAsString());
|
||||||
|
String mainBranch = json.getString("default_branch");
|
||||||
|
String language = json.getString("language", "<none>");
|
||||||
|
|
||||||
|
//this is a crude heuristic for class mods; only required for direct github import
|
||||||
|
//TODO make a more reliable way to distinguish java mod repos
|
||||||
|
if(language.equals("Java") || language.equals("Kotlin")){
|
||||||
|
githubImportJavaMod(repo);
|
||||||
|
}else{
|
||||||
|
githubImportBranch(mainBranch, repo, this::showStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this::importFail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void githubImportJavaMod(String repo){
|
||||||
|
//grab latest release
|
||||||
|
Core.net.httpGet(ghApi + "/repos/" + repo + "/releases/latest", res -> {
|
||||||
|
if(checkError(res)){
|
||||||
|
var json = Jval.read(res.getResultAsString());
|
||||||
|
var assets = json.get("assets").asArray();
|
||||||
|
|
||||||
|
//prioritize dexed jar, as that's what Sonnicon's mod template outputs
|
||||||
|
var dexedAsset = assets.find(j -> j.getString("name").startsWith("dexed") && j.getString("name").endsWith(".jar"));
|
||||||
|
var asset = dexedAsset == null ? assets.find(j -> j.getString("name").endsWith(".jar")) : dexedAsset;
|
||||||
|
|
||||||
|
if(asset != null){
|
||||||
|
//grab actual file
|
||||||
|
var url = asset.getString("browser_download_url");
|
||||||
|
Core.net.httpGet(url, result -> {
|
||||||
|
if(checkError(result)){
|
||||||
|
handleMod(repo, result);
|
||||||
|
}
|
||||||
|
}, this::importFail);
|
||||||
|
}else{
|
||||||
|
throw new ArcRuntimeException("No JAR file found in releases. Make sure you have a valid jar file in the mod's latest Github Release.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this::importFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkError(HttpResponse res){
|
||||||
|
if(res.getStatus() == HttpStatus.OK){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
showStatus(res.getStatus());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showStatus(HttpStatus status){
|
||||||
|
Core.app.post(() -> {
|
||||||
|
ui.showErrorMessage(Core.bundle.format("connectfail", Strings.capitalize(status.toString().toLowerCase())));
|
||||||
|
ui.loadfrag.hide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void githubImportBranch(String branch, String repo, Cons<HttpStatus> err){
|
private void githubImportBranch(String branch, String repo, Cons<HttpStatus> err){
|
||||||
Core.net.httpGet("https://api.github.com/repos/" + repo + "/zipball/" + branch, loc -> {
|
Core.net.httpGet(ghApi + "/repos/" + repo + "/zipball/" + branch, loc -> {
|
||||||
if(loc.getStatus() == HttpStatus.OK){
|
if(loc.getStatus() == HttpStatus.OK){
|
||||||
if(loc.getHeader("Location") != null){
|
if(loc.getHeader("Location") != null){
|
||||||
Core.net.httpGet(loc.getHeader("Location"), result -> {
|
Core.net.httpGet(loc.getHeader("Location"), result -> {
|
||||||
@@ -440,13 +616,13 @@ public class ModsDialog extends BaseDialog{
|
|||||||
}else{
|
}else{
|
||||||
handleMod(repo, result);
|
handleMod(repo, result);
|
||||||
}
|
}
|
||||||
}, t2 -> Core.app.post(() -> modError(t2)));
|
}, this::importFail);
|
||||||
}else{
|
}else{
|
||||||
handleMod(repo, loc);
|
handleMod(repo, loc);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
err.get(loc.getStatus());
|
err.get(loc.getStatus());
|
||||||
}
|
}
|
||||||
}, t2 -> Core.app.post(() -> modError(t2)));
|
}, this::importFail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,11 +409,11 @@ public class SettingsMenuDialog extends SettingsDialog{
|
|||||||
graphics.checkPref("animatedshields", !mobile);
|
graphics.checkPref("animatedshields", !mobile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ios){
|
//if(!ios){
|
||||||
graphics.checkPref("bloom", true, val -> renderer.toggleBloom(val));
|
graphics.checkPref("bloom", true, val -> renderer.toggleBloom(val));
|
||||||
}else{
|
//}else{
|
||||||
Core.settings.put("bloom", false);
|
// Core.settings.put("bloom", false);
|
||||||
}
|
//}
|
||||||
|
|
||||||
graphics.checkPref("pixelate", false, val -> {
|
graphics.checkPref("pixelate", false, val -> {
|
||||||
if(val){
|
if(val){
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class PlayerListFragment extends Fragment{
|
|||||||
menu.button("@close", this::toggle);
|
menu.button("@close", this::toggle);
|
||||||
}).margin(0f).pad(10f).growX();
|
}).margin(0f).pad(10f).growX();
|
||||||
|
|
||||||
}).touchable(Touchable.enabled).margin(14f);
|
}).touchable(Touchable.enabled).margin(14f).minWidth(360f);
|
||||||
});
|
});
|
||||||
|
|
||||||
rebuild();
|
rebuild();
|
||||||
|
|||||||
@@ -145,6 +145,8 @@ public class Block extends UnlockableContent{
|
|||||||
public boolean conveyorPlacement;
|
public boolean conveyorPlacement;
|
||||||
/** Whether to swap the diagonal placement modes. */
|
/** Whether to swap the diagonal placement modes. */
|
||||||
public boolean swapDiagonalPlacement;
|
public boolean swapDiagonalPlacement;
|
||||||
|
/** Build queue priority in schematics. */
|
||||||
|
public int schematicPriority = 0;
|
||||||
/**
|
/**
|
||||||
* The color of this block when displayed on the minimap or map preview.
|
* The color of this block when displayed on the minimap or map preview.
|
||||||
* Do not set manually! This is overridden when loading for most blocks.
|
* Do not set manually! This is overridden when loading for most blocks.
|
||||||
@@ -426,6 +428,12 @@ public class Block extends UnlockableContent{
|
|||||||
TextureRegion reg = getRequestRegion(req, list);
|
TextureRegion reg = getRequestRegion(req, list);
|
||||||
Draw.rect(reg, req.drawx(), req.drawy(), !rotate ? 0 : req.rotation * 90);
|
Draw.rect(reg, req.drawx(), req.drawy(), !rotate ? 0 : req.rotation * 90);
|
||||||
|
|
||||||
|
if(req.worldContext && player != null && teamRegion != null && teamRegion.found()){
|
||||||
|
if(teamRegions[player.team().id] == teamRegion) Draw.color(player.team().color);
|
||||||
|
Draw.rect(teamRegions[player.team().id], req.drawx(), req.drawy());
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
|
||||||
drawRequestConfig(req, list);
|
drawRequestConfig(req, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ public class ForceProjector extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRemoved(){
|
public void onRemoved(){
|
||||||
|
float radius = realRadius();
|
||||||
|
if(!broken && radius > 1f) Fx.forceShrink.at(x, y, radius, team.color);
|
||||||
super.onRemoved();
|
super.onRemoved();
|
||||||
drawer.remove();
|
drawer.remove();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class Turret extends ReloadTurret{
|
|||||||
|
|
||||||
public @Load(value = "@-base", fallback = "block-@size") TextureRegion baseRegion;
|
public @Load(value = "@-base", fallback = "block-@size") TextureRegion baseRegion;
|
||||||
public @Load("@-heat") TextureRegion heatRegion;
|
public @Load("@-heat") TextureRegion heatRegion;
|
||||||
|
public float elevation = -1f;
|
||||||
|
|
||||||
public Cons<TurretBuild> drawer = tile -> Draw.rect(region, tile.x + tr2.x, tile.y + tr2.y, tile.rotation - 90);
|
public Cons<TurretBuild> drawer = tile -> Draw.rect(region, tile.x + tr2.x, tile.y + tr2.y, tile.rotation - 90);
|
||||||
public Cons<TurretBuild> heatDrawer = tile -> {
|
public Cons<TurretBuild> heatDrawer = tile -> {
|
||||||
@@ -111,7 +112,7 @@ public class Turret extends ReloadTurret{
|
|||||||
super.setStats();
|
super.setStats();
|
||||||
|
|
||||||
stats.add(Stat.inaccuracy, (int)inaccuracy, StatUnit.degrees);
|
stats.add(Stat.inaccuracy, (int)inaccuracy, StatUnit.degrees);
|
||||||
stats.add(Stat.reload, 60f / reloadTime * (alternate ? 1 : shots), StatUnit.none);
|
stats.add(Stat.reload, 60f / (reloadTime + 1) * (alternate ? 1 : shots), StatUnit.none);
|
||||||
stats.add(Stat.targetsAir, targetAir);
|
stats.add(Stat.targetsAir, targetAir);
|
||||||
stats.add(Stat.targetsGround, targetGround);
|
stats.add(Stat.targetsGround, targetGround);
|
||||||
if(ammoPerShot != 1) stats.add(Stat.ammoUse, ammoPerShot, StatUnit.perShot);
|
if(ammoPerShot != 1) stats.add(Stat.ammoUse, ammoPerShot, StatUnit.perShot);
|
||||||
@@ -125,6 +126,7 @@ public class Turret extends ReloadTurret{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(shootLength < 0) shootLength = size * tilesize / 2f;
|
if(shootLength < 0) shootLength = size * tilesize / 2f;
|
||||||
|
if(elevation < 0) elevation = size / 2f;
|
||||||
|
|
||||||
super.init();
|
super.init();
|
||||||
}
|
}
|
||||||
@@ -234,7 +236,7 @@ public class Turret extends ReloadTurret{
|
|||||||
|
|
||||||
tr2.trns(rotation, -recoil);
|
tr2.trns(rotation, -recoil);
|
||||||
|
|
||||||
Drawf.shadow(region, x + tr2.x - (size / 2f), y + tr2.y - (size / 2f), rotation - 90);
|
Drawf.shadow(region, x + tr2.x - elevation, y + tr2.y - elevation, rotation - 90);
|
||||||
drawer.get(this);
|
drawer.get(this);
|
||||||
|
|
||||||
if(heatRegion != Core.atlas.find("error")){
|
if(heatRegion != Core.atlas.find("error")){
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public class Conveyor extends Block implements Autotiler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Block getReplacement(BuildPlan req, Seq<BuildPlan> requests){
|
public Block getReplacement(BuildPlan req, Seq<BuildPlan> requests){
|
||||||
Boolf<Point2> cont = p -> requests.contains(o -> o.x == req.x + p.x && o.y == req.y + p.y && o.rotation == req.rotation && (req.block instanceof Conveyor || req.block instanceof Junction));
|
Boolf<Point2> cont = p -> requests.contains(o -> o.x == req.x + p.x && o.y == req.y + p.y && (req.block instanceof Conveyor || req.block instanceof Junction));
|
||||||
return cont.get(Geometry.d4(req.rotation)) &&
|
return cont.get(Geometry.d4(req.rotation)) &&
|
||||||
cont.get(Geometry.d4(req.rotation - 2)) &&
|
cont.get(Geometry.d4(req.rotation - 2)) &&
|
||||||
req.tile() != null &&
|
req.tile() != null &&
|
||||||
|
|||||||
@@ -217,11 +217,9 @@ public class PayloadConveyor extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptPayload(Building source, Payload payload){
|
public boolean acceptPayload(Building source, Payload payload){
|
||||||
if(source == this){
|
return this.item == null
|
||||||
return this.item == null && payload.fits(payloadLimit);
|
&& payload.fits(payloadLimit)
|
||||||
}
|
&& (source == this || this.enabled && progress <= 5f);
|
||||||
//accepting payloads from units isn't supported
|
|
||||||
return this.item == null && progress <= 5f && payload.fits(payloadLimit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ public class StackConveyor extends Block implements Autotiler{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
|
Draw.z(Layer.block - 0.2f);
|
||||||
|
|
||||||
Draw.rect(regions[state], x, y, rotdeg());
|
Draw.rect(regions[state], x, y, rotdeg());
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
@@ -117,7 +119,7 @@ public class StackConveyor extends Block implements Autotiler{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.z(Layer.blockOver);
|
Draw.z(Layer.block - 0.1f);
|
||||||
|
|
||||||
Tile from = world.tile(link);
|
Tile from = world.tile(link);
|
||||||
|
|
||||||
@@ -145,6 +147,12 @@ public class StackConveyor extends Block implements Autotiler{
|
|||||||
Draw.rect(lastItem.icon(Cicon.medium), Tmp.v1.x, Tmp.v1.y, size, size, 0);
|
Draw.rect(lastItem.icon(Cicon.medium), Tmp.v1.x, Tmp.v1.y, size, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawCracks(){
|
||||||
|
Draw.z(Layer.block - 0.15f);
|
||||||
|
super.drawCracks();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onProximityUpdate(){
|
public void onProximityUpdate(){
|
||||||
super.onProximityUpdate();
|
super.onProximityUpdate();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class LiquidBridge extends ItemBridge{
|
|||||||
|
|
||||||
Building other = world.build(link);
|
Building other = world.build(link);
|
||||||
if(other == null || !linkValid(tile, other.tile())){
|
if(other == null || !linkValid(tile, other.tile())){
|
||||||
dumpLiquid(liquids.current());
|
dumpLiquid(liquids.current(), 1f);
|
||||||
}else{
|
}else{
|
||||||
((ItemBridgeBuild)other).incoming.add(tile.pos());
|
((ItemBridgeBuild)other).incoming.add(tile.pos());
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class LiquidExtendingBridge extends ExtendingItemBridge{
|
|||||||
|
|
||||||
Building other = world.build(link);
|
Building other = world.build(link);
|
||||||
if(other == null || !linkValid(tile, other.tile())){
|
if(other == null || !linkValid(tile, other.tile())){
|
||||||
dumpLiquid(liquids.current());
|
dumpLiquid(liquids.current(), 1f);
|
||||||
}else{
|
}else{
|
||||||
((ItemBridgeBuild)other).incoming.add(tile.pos());
|
((ItemBridgeBuild)other).incoming.add(tile.pos());
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class LogicBlock extends Block{
|
|||||||
entity.links.add(out);
|
entity.links.add(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.updateCode();
|
entity.updateCode(entity.code, true, null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,15 +277,11 @@ public class LogicBlock extends Block{
|
|||||||
return bname + outnum;
|
return bname + outnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCode(){
|
|
||||||
updateCode(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateCode(String str){
|
public void updateCode(String str){
|
||||||
updateCodeVars(str, null);
|
updateCode(str, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCodeVars(String str, Cons<LAssembler> assemble){
|
public void updateCode(String str, boolean keep, Cons<LAssembler> assemble){
|
||||||
if(str != null){
|
if(str != null){
|
||||||
code = str;
|
code = str;
|
||||||
|
|
||||||
@@ -317,6 +313,19 @@ public class LogicBlock extends Block{
|
|||||||
asm.putConst("@links", executor.links.length);
|
asm.putConst("@links", executor.links.length);
|
||||||
asm.putConst("@ipt", instructionsPerTick);
|
asm.putConst("@ipt", instructionsPerTick);
|
||||||
|
|
||||||
|
if(keep){
|
||||||
|
//store any older variables
|
||||||
|
for(Var var : executor.vars){
|
||||||
|
boolean unit = var.name.equals("@unit");
|
||||||
|
if(!var.constant || unit){
|
||||||
|
BVar dest = asm.getVar(var.name);
|
||||||
|
if(dest != null && (!dest.constant || unit)){
|
||||||
|
dest.value = var.isobj ? var.objval : var.numval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//inject any extra variables
|
//inject any extra variables
|
||||||
if(assemble != null){
|
if(assemble != null){
|
||||||
assemble.get(asm);
|
assemble.get(asm);
|
||||||
@@ -397,7 +406,7 @@ public class LogicBlock extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(changed){
|
if(changed){
|
||||||
updateCode();
|
updateCode(code, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(enabled){
|
if(enabled){
|
||||||
@@ -555,7 +564,7 @@ public class LogicBlock extends Block{
|
|||||||
//skip memory, it isn't used anymore
|
//skip memory, it isn't used anymore
|
||||||
read.skip(memory * 8);
|
read.skip(memory * 8);
|
||||||
|
|
||||||
updateCodeVars(code, asm -> {
|
updateCode(code, false, asm -> {
|
||||||
|
|
||||||
//load up the variables that were stored
|
//load up the variables that were stored
|
||||||
for(int i = 0; i < varcount; i++){
|
for(int i = 0; i < varcount; i++){
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import mindustry.entities.*;
|
|||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.logic.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
@@ -122,6 +123,12 @@ public class ImpactReactor extends PowerGenerator{
|
|||||||
Drawf.light(team, x, y, (110f + Mathf.absin(5, 5f)) * warmup, Tmp.c1.set(plasma2).lerp(plasma1, Mathf.absin(7f, 0.2f)), 0.8f * warmup);
|
Drawf.light(team, x, y, (110f + Mathf.absin(5, 5f)) * warmup, Tmp.c1.set(plasma2).lerp(plasma1, Mathf.absin(7f, 0.2f)), 0.8f * warmup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double sense(LAccess sensor){
|
||||||
|
if(sensor == LAccess.heat) return warmup;
|
||||||
|
return super.sense(sensor);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyed(){
|
public void onDestroyed(){
|
||||||
super.onDestroyed();
|
super.onDestroyed();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import arc.util.io.*;
|
|||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.logic.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
@@ -32,6 +33,15 @@ public class LightBlock extends Block{
|
|||||||
public int color = Pal.accent.rgba();
|
public int color = Pal.accent.rgba();
|
||||||
public float smoothTime = 1f;
|
public float smoothTime = 1f;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void control(LAccess type, double p1, double p2, double p3, double p4){
|
||||||
|
if(type == LAccess.color){
|
||||||
|
color = Color.rgba8888((float)p1, (float)p2, (float)p3, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.control(type, p1, p2, p3, p4);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
super.draw();
|
super.draw();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public class PowerDiode extends Block{
|
|||||||
insulated = true;
|
insulated = true;
|
||||||
group = BlockGroup.power;
|
group = BlockGroup.power;
|
||||||
noUpdateDisabled = true;
|
noUpdateDisabled = true;
|
||||||
|
schematicPriority = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ public class PowerGraph{
|
|||||||
lastPowerNeeded = powerNeeded;
|
lastPowerNeeded = powerNeeded;
|
||||||
lastPowerProduced = powerProduced;
|
lastPowerProduced = powerProduced;
|
||||||
|
|
||||||
lastScaledPowerIn = powerProduced / Time.delta;
|
lastScaledPowerIn = (powerProduced + energyDelta) / Time.delta;
|
||||||
lastScaledPowerOut = powerNeeded / Time.delta;
|
lastScaledPowerOut = powerNeeded / Time.delta;
|
||||||
lastCapacity = getTotalBatteryCapacity();
|
lastCapacity = getTotalBatteryCapacity();
|
||||||
lastPowerStored = getBatteryStored();
|
lastPowerStored = getBatteryStored();
|
||||||
@@ -249,6 +249,8 @@ public class PowerGraph{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addGraph(PowerGraph graph){
|
public void addGraph(PowerGraph graph){
|
||||||
|
if(graph == this) return;
|
||||||
|
|
||||||
for(Building tile : graph.all){
|
for(Building tile : graph.all){
|
||||||
add(tile);
|
add(tile);
|
||||||
}
|
}
|
||||||
@@ -283,25 +285,24 @@ public class PowerGraph{
|
|||||||
Building child = queue.removeFirst();
|
Building child = queue.removeFirst();
|
||||||
add(child);
|
add(child);
|
||||||
for(Building next : child.getPowerConnections(outArray2)){
|
for(Building next : child.getPowerConnections(outArray2)){
|
||||||
if(!closedSet.contains(next.pos())){
|
if(closedSet.add(next.pos())){
|
||||||
queue.addLast(next);
|
queue.addLast(next);
|
||||||
closedSet.add(next.pos());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeSingle(Building tile){
|
/** Used for unit tests only. */
|
||||||
all.remove(tile, true);
|
public void removeList(Building build){
|
||||||
producers.remove(tile, true);
|
all.remove(build);
|
||||||
consumers.remove(tile, true);
|
producers.remove(build);
|
||||||
batteries.remove(tile, true);
|
consumers.remove(build);
|
||||||
|
batteries.remove(build);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Note that this does not actually remove the building from the graph;
|
||||||
|
* it creates *new* graphs that contain the correct buildings. */
|
||||||
public void remove(Building tile){
|
public void remove(Building tile){
|
||||||
removeSingle(tile);
|
|
||||||
//begin by clearing the closed set
|
|
||||||
closedSet.clear();
|
|
||||||
|
|
||||||
//go through all the connections of this tile
|
//go through all the connections of this tile
|
||||||
for(Building other : tile.getPowerConnections(outArray1)){
|
for(Building other : tile.getPowerConnections(outArray1)){
|
||||||
@@ -317,17 +318,15 @@ public class PowerGraph{
|
|||||||
while(queue.size > 0){
|
while(queue.size > 0){
|
||||||
//get child from queue
|
//get child from queue
|
||||||
Building child = queue.removeFirst();
|
Building child = queue.removeFirst();
|
||||||
//remove it from this graph
|
|
||||||
removeSingle(child);
|
|
||||||
//add it to the new branch graph
|
//add it to the new branch graph
|
||||||
graph.add(child);
|
graph.add(child);
|
||||||
//go through connections
|
//go through connections
|
||||||
for(Building next : child.getPowerConnections(outArray2)){
|
for(Building next : child.getPowerConnections(outArray2)){
|
||||||
//make sure it hasn't looped back, and that the new graph being assigned hasn't already been assigned
|
//make sure it hasn't looped back, and that the new graph being assigned hasn't already been assigned
|
||||||
//also skip closed tiles
|
//also skip closed tiles
|
||||||
if(next != tile && next.power.graph != graph && !closedSet.contains(next.pos())){
|
if(next != tile && next.power.graph != graph){
|
||||||
|
graph.add(next);
|
||||||
queue.addLast(next);
|
queue.addLast(next);
|
||||||
closedSet.add(next.pos());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class PowerNode extends PowerBlock{
|
|||||||
outputsPower = false;
|
outputsPower = false;
|
||||||
canOverdrive = false;
|
canOverdrive = false;
|
||||||
swapDiagonalPlacement = true;
|
swapDiagonalPlacement = true;
|
||||||
|
schematicPriority = -10;
|
||||||
drawDisabled = false;
|
drawDisabled = false;
|
||||||
|
|
||||||
config(Integer.class, (entity, value) -> {
|
config(Integer.class, (entity, value) -> {
|
||||||
@@ -221,12 +222,15 @@ public class PowerNode extends PowerBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawRequestConfigTop(BuildPlan req, Eachable<BuildPlan> list){
|
public void drawRequestConfigTop(BuildPlan req, Eachable<BuildPlan> list){
|
||||||
if(req.config instanceof Point2[]){
|
if(req.config instanceof Point2[] ps){
|
||||||
setupColor(1f);
|
setupColor(1f);
|
||||||
for(Point2 point : (Point2[])req.config){
|
for(Point2 point : ps){
|
||||||
|
int px = req.x + point.x, py = req.y + point.y;
|
||||||
otherReq = null;
|
otherReq = null;
|
||||||
list.each(other -> {
|
list.each(other -> {
|
||||||
if((other.x == req.x + point.x && other.y == req.y + point.y) && other != req){
|
if(other.block != null
|
||||||
|
&& (px >= other.x - ((other.block.size-1)/2) && py >= other.y - ((other.block.size-1)/2) && px <= other.x + other.block.size/2 && py <= other.y + other.block.size/2)
|
||||||
|
&& other != req && other.block.hasPower){
|
||||||
otherReq = other;
|
otherReq = other;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class SolarGenerator extends PowerGenerator{
|
|||||||
|
|
||||||
public SolarGenerator(String name){
|
public SolarGenerator(String name){
|
||||||
super(name);
|
super(name);
|
||||||
//remove the BlockFlag.producer flag to make this a lower priority target than other generators.
|
//remove the BlockFlag.generator flag to make this a lower priority target than other generators.
|
||||||
flags = EnumSet.of();
|
flags = EnumSet.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,9 +106,10 @@ public class Reconstructor extends UnitBlock{
|
|||||||
@Override
|
@Override
|
||||||
public boolean acceptPayload(Building source, Payload payload){
|
public boolean acceptPayload(Building source, Payload payload){
|
||||||
return this.payload == null
|
return this.payload == null
|
||||||
|
&& (this.enabled || source == this)
|
||||||
&& relativeTo(source) != rotation
|
&& relativeTo(source) != rotation
|
||||||
&& payload instanceof UnitPayload
|
&& payload instanceof UnitPayload pay
|
||||||
&& hasUpgrade(((UnitPayload)payload).unit.type);
|
&& hasUpgrade(pay.unit.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import arc.math.*;
|
|||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import arc.util.io.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -123,5 +124,26 @@ public class RepairPoint extends Block{
|
|||||||
public BlockStatus status(){
|
public BlockStatus status(){
|
||||||
return Mathf.equal(efficiency(), 0f, 0.01f) ? BlockStatus.noInput : cons.status();
|
return Mathf.equal(efficiency(), 0f, 0.01f) ? BlockStatus.noInput : cons.status();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Writes write){
|
||||||
|
super.write(write);
|
||||||
|
|
||||||
|
write.f(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(Reads read, byte revision){
|
||||||
|
super.read(read, revision);
|
||||||
|
|
||||||
|
if(revision >= 1){
|
||||||
|
rotation = read.f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte version(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
if(plan.unit.unlockedNow()){
|
if(plan.unit.unlockedNow()){
|
||||||
table.image(plan.unit.icon(Cicon.small)).size(8 * 3).padRight(2).right();
|
table.image(plan.unit.icon(Cicon.small)).size(8 * 3).padRight(2).right();
|
||||||
table.add(plan.unit.localizedName).left();
|
table.add(plan.unit.localizedName).left();
|
||||||
|
table.add(Strings.autoFixed(plan.time / 60f, 1) + " " + Core.bundle.get("unit.seconds")).color(Color.lightGray).padLeft(12).left();
|
||||||
table.row();
|
table.row();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class ConsumeLiquid extends ConsumeLiquidBase{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean valid(Building entity){
|
public boolean valid(Building entity){
|
||||||
return entity != null && entity.liquids != null && entity.liquids.get(liquid) >= use(entity);
|
return entity != null && entity.liquids != null && entity.liquids.get(liquid) >= amount * entity.edelta();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.util.*;
|
|||||||
/** Describes one type of stat for content. */
|
/** Describes one type of stat for content. */
|
||||||
public enum Stat{
|
public enum Stat{
|
||||||
health,
|
health,
|
||||||
|
armor,
|
||||||
size,
|
size,
|
||||||
displaySize,
|
displaySize,
|
||||||
buildTime,
|
buildTime,
|
||||||
@@ -15,6 +16,7 @@ public enum Stat{
|
|||||||
explosiveness,
|
explosiveness,
|
||||||
flammability,
|
flammability,
|
||||||
radioactivity,
|
radioactivity,
|
||||||
|
charge,
|
||||||
heatCapacity,
|
heatCapacity,
|
||||||
viscosity,
|
viscosity,
|
||||||
temperature,
|
temperature,
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public class DesktopLauncher extends ClientLauncher{
|
|||||||
steamError = e;
|
steamError = e;
|
||||||
loadError = true;
|
loadError = true;
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
try(OutputStream s = new FileOutputStream(new File("steam-error-log-" + System.nanoTime() + ".txt"))){
|
try(OutputStream s = new FileOutputStream("steam-error-log-" + System.nanoTime() + ".txt")){
|
||||||
String log = Strings.neatError(e);
|
String log = Strings.neatError(e);
|
||||||
s.write(log.getBytes());
|
s.write(log.getBytes());
|
||||||
}catch(Exception e2){
|
}catch(Exception e2){
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ public class SStats implements SteamUserStatsCallback{
|
|||||||
stats.storeStats();
|
stats.storeStats();
|
||||||
}
|
}
|
||||||
}, statSavePeriod * 60, statSavePeriod * 60);
|
}, statSavePeriod * 60, statSavePeriod * 60);
|
||||||
|
|
||||||
|
if(Items.thorium.unlocked()) obtainThorium.complete();
|
||||||
|
if(Items.titanium.unlocked()) obtainTitanium.complete();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
fastlane/metadata/android/en-US/changelogs/29801.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/29801.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[This is a truncated changelog, see Github for full notes]
|
||||||
|
As 6.0 is more or less stable now, updates have slowed down significantly. This is likely to be one of the last notable releases before 7.0.
|
||||||
|
|
||||||
|
- Fixed same-line logic comments not parsing
|
||||||
|
- Fixed mass driver rotating before payload is received
|
||||||
|
- Fixed bullets dealing splash damage twice upon collision - splash damage of certain bullets has been increased to compensate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
6
fastlane/metadata/android/en-US/changelogs/29804.txt
Normal file
6
fastlane/metadata/android/en-US/changelogs/29804.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[This is a truncated changelog, see Github for full notes]
|
||||||
|
- Fixed negative numbers not displaying properly in power nodes
|
||||||
|
- Fixed mod minVersion parsing
|
||||||
|
- Fixed mods disappearing after import [Android]
|
||||||
|
- Disabled duplicate IP prevention system
|
||||||
|
- Added mod browser sort order button
|
||||||
8
fastlane/metadata/android/en-US/changelogs/29811.txt
Normal file
8
fastlane/metadata/android/en-US/changelogs/29811.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[This is a truncated changelog, see Github for full notes]
|
||||||
|
- Fixed logic blocks resetting state on map load or connection changes
|
||||||
|
- Fixed "#" in any logic string breaking instructions
|
||||||
|
- Fixed crawlers not exploding next to cores
|
||||||
|
- Fixed certain status effect combinations not triggering damage
|
||||||
|
- Fixed waves being infinitely skippable when game is paused
|
||||||
|
- Fixed constructed blocks sometimes having low health on servers'
|
||||||
|
- Fixed enemy core items not syncing
|
||||||
52
fastlane/metadata/android/ro/full_description.txt
Normal file
52
fastlane/metadata/android/ro/full_description.txt
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
Crează benzi elaborate de aprovizionare pt a-ți alimenta armele cu muniție, produ materiale de construcție și apără-ți baza de inamici. Joacă cu prietenii pe multiplayer în co-op sau provoacă-i la un meci PvP.
|
||||||
|
|
||||||
|
<h2>Funcțiile Jocului</h2>
|
||||||
|
|
||||||
|
- Construiește clădiri pt a fabrica o mare varietate de materiale avansate
|
||||||
|
- Apara-ți baza de inamici
|
||||||
|
- Joacă cu prietenii pe multiplayer în co-op sau provoacă-i la un meci PvP
|
||||||
|
- Distribuie lichide și luptă împotriva amenințărilor constante, cum ar fi incendiile devastatoare sau raidurile inamice
|
||||||
|
- Eficientizează-ți producția folosind lichid de răcire și lubrifiante
|
||||||
|
- Produ o variatate de unități militare pt managementul automat al bazei sau atacarea bazelor inamice
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Campanie</h2>
|
||||||
|
|
||||||
|
- Capturează planeta Serpulo avansând prin peste 250 de sectoare genereate procedural și 16 harți create manual
|
||||||
|
- Capturează teritoriul și construiește fabrici pt producția de resurse în timp ce joci în alte sectoare
|
||||||
|
- Apără-ți sectoarele de invaziile inamice periodice
|
||||||
|
- Coordonează distribuția de resurse între sectoare folosind platforme de lansare
|
||||||
|
- Cercetează noi fabrici pt a-ți crește progresul tehnologic
|
||||||
|
- Invită-ți prietenii pt a duce misiuni la bun sfârșit împreună
|
||||||
|
- Peste 130 de structuri precum fabrici și arme de cercetat și stăpânit
|
||||||
|
- 33 de tipuri diferite de drone, roboți și nave
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Moduri de Joc</h2>
|
||||||
|
|
||||||
|
- <b>Supraviețuire</b>: Construiește arme pt a te apăra de inamici în stil tower defense. Rezistă cât de mult se poate. Îți poți lansa nucelul pt a folosi resursele adunate pt cercetare. Pregătește-ți baza pt a supraviețui atacurilor intermitente ale gardienilor aerieni.
|
||||||
|
- <b>Atac</b>: Construiește fabrici de unități pt a distruge nucleele inamice, în timp ce îți aperi baza de valurile de inamici. Crează o variatate de tipuri de unități ofensive și de suport pt a te ajuta să-ți atingi obiectivul. Poți activa inteligența artificială a inamicilor, iar ei vor construi structuri pt a se apăra împotriva ta, oferind o extra provocare.
|
||||||
|
- <b>PvP</b>: Concurează cu alți jucători din până la 4 echipe și câștigă distrugându-le nucleele. Construiește unități sau atacă direct alte baze.
|
||||||
|
- <b>Sandbox</b>: Joacă folosind resurse infinite, fără niciun risc din partea inamicilor. Folosește blocuri sursă de lichid și material specifice modului sandbox pt a testa designuri și cheamă inamicul când vrei.
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Jocuri Personalizate și Multiplayer Între Platforme</h2>
|
||||||
|
|
||||||
|
- 16 hărți create manual pt jocuri personalizate, în plus față de campanie
|
||||||
|
- Joacă co-op, PvP sau sandbox
|
||||||
|
- Alătură-te unui server public dedicat, sau invită-ți prietenii pt propria sesiune privată
|
||||||
|
- Reguli de joc personalizabile: Schimbă costul blocurilor, puterea inamicilor, resursele inițiale, timpul dintre valuri și altele
|
||||||
|
- Moduri de joc complet configurabile: Combină modurile PvP și PvE
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Editorul de Hărți</h2>
|
||||||
|
|
||||||
|
- Modifică terenul folosind interfața editorului
|
||||||
|
- Editează și vizualizează structurile în joc
|
||||||
|
- Moduri de unealtă configurabile: Schimbă modul cum funcționează fiecare unealtă
|
||||||
|
- Un sistem robust de generare a hărților, cu multe tipuri diferite de filtre pt manipularea procedurală a terenului
|
||||||
|
- Aplică zgomot vizual, distorsionare, netezire, eroziune, simetrie, minereuri generate și teren aleatoriu pt hărțile tale
|
||||||
|
- Configurează atât generarea aleatorie a minereurilor cât și poziția râurilor și a zonelor cu resurse
|
||||||
|
- Configurează structura valurilor inamice
|
||||||
|
- Personalizează regulile de bază ale hărții
|
||||||
|
- Folosește peste 80 de blocuri de teren diferite
|
||||||
1
fastlane/metadata/android/ro/short_description.txt
Normal file
1
fastlane/metadata/android/ro/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Un joc tower defense bazat pe industrie.
|
||||||
1
fastlane/metadata/android/ro/summary.txt
Normal file
1
fastlane/metadata/android/ro/summary.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Un joc tower defense bazat pe industrie.
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user