Merge branch 'master' into master
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -4,4 +4,4 @@ about: Suggest an idea for this project
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Do not make a new issue for feature requests. Instead, post it in #545.
|
**Do not make a new issue for feature requests!** Instead, post it in #545.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ _[Wiki](https://mindustrygame.github.io/wiki)_
|
|||||||
Bleeding-edge live builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). Old builds might still be on [jenkins](https://jenkins.hellomouse.net/job/mindustry/).
|
Bleeding-edge live builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). Old builds might still be on [jenkins](https://jenkins.hellomouse.net/job/mindustry/).
|
||||||
|
|
||||||
If you'd rather compile on your own, follow these instructions.
|
If you'd rather compile on your own, follow these instructions.
|
||||||
First, make sure you have Java 8 and JDK 8 installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands:
|
First, make sure you have [Java 8](https://www.java.com/en/download/) and [JDK 8](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands:
|
||||||
|
|
||||||
#### Windows
|
#### Windows
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public class AssetsAnnotationProcessor extends AbstractProcessor{
|
|||||||
path = Paths.get(Utils.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
path = Paths.get(Utils.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
||||||
.toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
|
.toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
|
||||||
.getParent().getParent().getParent().getParent().getParent().getParent().toString();
|
.getParent().getParent().getParent().getParent().getParent().getParent().toString();
|
||||||
|
path = path.replace("%20", " ");
|
||||||
|
|
||||||
processSounds("Sounds", path + "/assets/sounds", "io.anuke.arc.audio.Sound");
|
processSounds("Sounds", path + "/assets/sounds", "io.anuke.arc.audio.Sound");
|
||||||
processSounds("Musics", path + "/assets/music", "io.anuke.arc.audio.Music");
|
processSounds("Musics", path + "/assets/music", "io.anuke.arc.audio.Music");
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ project(":desktop"){
|
|||||||
compile "com.code-disaster.steamworks4j:steamworks4j-server:$steamworksVersion"
|
compile "com.code-disaster.steamworks4j:steamworks4j-server:$steamworksVersion"
|
||||||
|
|
||||||
compile arcModule("backends:backend-sdl")
|
compile arcModule("backends:backend-sdl")
|
||||||
compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.2'
|
compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
core/assets-raw/sprites/blocks/distribution/inverted-sorter.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 200 B After Width: | Height: | Size: 1.4 KiB |
@@ -45,7 +45,6 @@ database = Core Database
|
|||||||
savegame = Save Game
|
savegame = Save Game
|
||||||
loadgame = Load Game
|
loadgame = Load Game
|
||||||
joingame = Join Game
|
joingame = Join Game
|
||||||
addplayers = Add/Remove Players
|
|
||||||
customgame = Custom Game
|
customgame = Custom Game
|
||||||
newgame = New Game
|
newgame = New Game
|
||||||
none = <none>
|
none = <none>
|
||||||
@@ -71,6 +70,7 @@ mods.alpha = [accent](Alpha)
|
|||||||
mods = Mods
|
mods = Mods
|
||||||
mods.none = [LIGHT_GRAY]No mods found!
|
mods.none = [LIGHT_GRAY]No mods found!
|
||||||
mods.guide = Modding Guide
|
mods.guide = Modding Guide
|
||||||
|
mods.report = Report Bug
|
||||||
mod.enabled = [lightgray]Enabled
|
mod.enabled = [lightgray]Enabled
|
||||||
mod.disabled = [scarlet]Disabled
|
mod.disabled = [scarlet]Disabled
|
||||||
mod.disable = Disable
|
mod.disable = Disable
|
||||||
@@ -78,6 +78,7 @@ mod.enable = Enable
|
|||||||
mod.requiresrestart = The game will now close to apply the mod changes.
|
mod.requiresrestart = The game will now close to apply the mod changes.
|
||||||
mod.reloadrequired = [scarlet]Reload Required
|
mod.reloadrequired = [scarlet]Reload Required
|
||||||
mod.import = Import Mod
|
mod.import = Import Mod
|
||||||
|
mod.import.github = Import Github Mod
|
||||||
mod.remove.confirm = This mod will be deleted.
|
mod.remove.confirm = This mod will be deleted.
|
||||||
mod.author = [LIGHT_GRAY]Author:[] {0}
|
mod.author = [LIGHT_GRAY]Author:[] {0}
|
||||||
mod.missing = This save contains mods that you have recently updated or no longer have installed. Save corruption may occur. Are you sure you want to load it?\n[lightgray]Mods:\n{0}
|
mod.missing = This save contains mods that you have recently updated or no longer have installed. Save corruption may occur. Are you sure you want to load it?\n[lightgray]Mods:\n{0}
|
||||||
@@ -162,7 +163,6 @@ server.port = Port:
|
|||||||
server.addressinuse = Address already in use!
|
server.addressinuse = Address already in use!
|
||||||
server.invalidport = Invalid port number!
|
server.invalidport = Invalid port number!
|
||||||
server.error = [crimson]Error hosting server.
|
server.error = [crimson]Error hosting server.
|
||||||
save.old = This save is for an older version of the game, and can no longer be used.\n\n[lightgray]Save backwards compatibility will be implemented in the full 4.0 release.
|
|
||||||
save.new = New Save
|
save.new = New Save
|
||||||
save.overwrite = Are you sure you want to overwrite\nthis save slot?
|
save.overwrite = Are you sure you want to overwrite\nthis save slot?
|
||||||
overwrite = Overwrite
|
overwrite = Overwrite
|
||||||
@@ -216,6 +216,9 @@ quit.confirm.tutorial = Are you sure you know what you're doing?\nThe tutorial c
|
|||||||
loading = [accent]Loading...
|
loading = [accent]Loading...
|
||||||
reloading = [accent]Reloading Mods...
|
reloading = [accent]Reloading Mods...
|
||||||
saving = [accent]Saving...
|
saving = [accent]Saving...
|
||||||
|
cancelbuilding = [accent][[{0}][] to clear plan
|
||||||
|
pausebuilding = [accent][[{0}][] to pause building
|
||||||
|
resumebuilding = [scarlet][[{0}][] to resume building
|
||||||
wave = [accent]Wave {0}
|
wave = [accent]Wave {0}
|
||||||
wave.waiting = [lightgray]Wave in {0}
|
wave.waiting = [lightgray]Wave in {0}
|
||||||
wave.waveInProgress = [lightgray]Wave in progress
|
wave.waveInProgress = [lightgray]Wave in progress
|
||||||
@@ -376,7 +379,6 @@ campaign = Campaign
|
|||||||
load = Load
|
load = Load
|
||||||
save = Save
|
save = Save
|
||||||
fps = FPS: {0}
|
fps = FPS: {0}
|
||||||
tps = TPS: {0}
|
|
||||||
ping = Ping: {0}ms
|
ping = Ping: {0}ms
|
||||||
language.restart = Please restart your game for the language settings to take effect.
|
language.restart = Please restart your game for the language settings to take effect.
|
||||||
settings = Settings
|
settings = Settings
|
||||||
@@ -389,8 +391,10 @@ donate = Donate
|
|||||||
abandon = Abandon
|
abandon = Abandon
|
||||||
abandon.text = This zone and all its resources will be lost to the enemy.
|
abandon.text = This zone and all its resources will be lost to the enemy.
|
||||||
locked = Locked
|
locked = Locked
|
||||||
complete = [lightgray]Reach:
|
complete = [lightgray]Complete:
|
||||||
zone.requirement = Wave {0} in zone {1}
|
requirement.wave = Reach Wave {0} in {1}
|
||||||
|
requirement.core = Destroy Enemy Core in {0}
|
||||||
|
requirement.unlock = Unlock {0}
|
||||||
resume = Resume Zone:\n[lightgray]{0}
|
resume = Resume Zone:\n[lightgray]{0}
|
||||||
bestwave = [lightgray]Best Wave: {0}
|
bestwave = [lightgray]Best Wave: {0}
|
||||||
launch = < LAUNCH >
|
launch = < LAUNCH >
|
||||||
@@ -401,11 +405,13 @@ launch.confirm = This will launch all resources in your core.\nYou will not be a
|
|||||||
launch.skip.confirm = If you skip now, you will not be able to launch until later waves.
|
launch.skip.confirm = If you skip now, you will not be able to launch until later waves.
|
||||||
uncover = Uncover
|
uncover = Uncover
|
||||||
configure = Configure Loadout
|
configure = Configure Loadout
|
||||||
configure.locked = [lightgray]Unlock configuring loadout: Wave {0}.
|
bannedblocks = Banned Blocks
|
||||||
|
addall = Add All
|
||||||
|
configure.locked = [lightgray]Unlock configuring loadout: {0}.
|
||||||
configure.invalid = Amount must be a number between 0 and {0}.
|
configure.invalid = Amount must be a number between 0 and {0}.
|
||||||
zone.unlocked = [lightgray]{0} unlocked.
|
zone.unlocked = [lightgray]{0} unlocked.
|
||||||
zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met.
|
zone.requirement.complete = Requirement for {0} completed:[lightgray]\n{1}
|
||||||
zone.config.complete = Wave {0} reached:\nLoadout config unlocked.
|
zone.config.unlocked = Loadout unlocked:[lightgray]\n{0}
|
||||||
zone.resources = [lightgray]Resources Detected:
|
zone.resources = [lightgray]Resources Detected:
|
||||||
zone.objective = [lightgray]Objective: [accent]{0}
|
zone.objective = [lightgray]Objective: [accent]{0}
|
||||||
zone.objective.survival = Survive
|
zone.objective.survival = Survive
|
||||||
@@ -466,12 +472,13 @@ settings.cleardata = Clear Game Data...
|
|||||||
settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone!
|
settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone!
|
||||||
settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit.
|
settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit.
|
||||||
paused = [accent]< Paused >
|
paused = [accent]< Paused >
|
||||||
|
clear = Clear
|
||||||
|
banned = [scarlet]Banned
|
||||||
yes = Yes
|
yes = Yes
|
||||||
no = No
|
no = No
|
||||||
info.title = Info
|
info.title = Info
|
||||||
error.title = [crimson]An error has occured
|
error.title = [crimson]An error has occured
|
||||||
error.crashtitle = An error has occured
|
error.crashtitle = An error has occured
|
||||||
attackpvponly = [scarlet]Only available in Attack/PvP modes
|
|
||||||
blocks.input = Input
|
blocks.input = Input
|
||||||
blocks.output = Output
|
blocks.output = Output
|
||||||
blocks.booster = Booster
|
blocks.booster = Booster
|
||||||
@@ -556,6 +563,7 @@ category.optional = Optional Enhancements
|
|||||||
setting.landscape.name = Lock Landscape
|
setting.landscape.name = Lock Landscape
|
||||||
setting.shadows.name = Shadows
|
setting.shadows.name = Shadows
|
||||||
setting.linear.name = Linear Filtering
|
setting.linear.name = Linear Filtering
|
||||||
|
setting.hints.name = Hints
|
||||||
setting.animatedwater.name = Animated Water
|
setting.animatedwater.name = Animated Water
|
||||||
setting.animatedshields.name = Animated Shields
|
setting.animatedshields.name = Animated Shields
|
||||||
setting.antialias.name = Antialias[lightgray] (requires restart)[]
|
setting.antialias.name = Antialias[lightgray] (requires restart)[]
|
||||||
@@ -583,7 +591,6 @@ setting.fullscreen.name = Fullscreen
|
|||||||
setting.borderlesswindow.name = Borderless Window[lightgray] (may require restart)
|
setting.borderlesswindow.name = Borderless Window[lightgray] (may require restart)
|
||||||
setting.fps.name = Show FPS
|
setting.fps.name = Show FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Show Power Lasers
|
|
||||||
setting.pixelate.name = Pixelate[lightgray] (disables animations)
|
setting.pixelate.name = Pixelate[lightgray] (disables animations)
|
||||||
setting.minimap.name = Show Minimap
|
setting.minimap.name = Show Minimap
|
||||||
setting.musicvol.name = Music Volume
|
setting.musicvol.name = Music Volume
|
||||||
@@ -595,8 +602,10 @@ setting.crashreport.name = Send Anonymous Crash Reports
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chat Opacity
|
setting.chatopacity.name = Chat Opacity
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Display Player Bubble Chat
|
setting.playerchat.name = Display Player Bubble Chat
|
||||||
public.confirm = Do you want to make your game public?\n[lightgray]This can be changed later in Settings->Game->Public Game Visibility.
|
public.confirm = Do you want to make your game public?\n[accent]Anyone will be able to join your games.\n[lightgray]This can be changed later in Settings->Game->Public Game Visibility.
|
||||||
|
public.beta = Note that beta versions of the game cannot make public lobbies.
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
setting.bloom.name = Bloom
|
setting.bloom.name = Bloom
|
||||||
@@ -610,6 +619,7 @@ command.rally = Rally
|
|||||||
command.retreat = Retreat
|
command.retreat = Retreat
|
||||||
keybind.gridMode.name = Block Select
|
keybind.gridMode.name = Block Select
|
||||||
keybind.gridModeShift.name = Category Select
|
keybind.gridModeShift.name = Category Select
|
||||||
|
keybind.clear_building.name = Clear Building
|
||||||
keybind.press = Press a key...
|
keybind.press = Press a key...
|
||||||
keybind.press.axis = Press an axis or key...
|
keybind.press.axis = Press an axis or key...
|
||||||
keybind.screenshot.name = Map Screenshot
|
keybind.screenshot.name = Map Screenshot
|
||||||
@@ -626,6 +636,7 @@ keybind.zoom_hold.name = Zoom Hold
|
|||||||
keybind.zoom.name = Zoom
|
keybind.zoom.name = Zoom
|
||||||
keybind.menu.name = Menu
|
keybind.menu.name = Menu
|
||||||
keybind.pause.name = Pause
|
keybind.pause.name = Pause
|
||||||
|
keybind.pause_building.name = Pause/Resume Building
|
||||||
keybind.minimap.name = Minimap
|
keybind.minimap.name = Minimap
|
||||||
keybind.dash.name = Dash
|
keybind.dash.name = Dash
|
||||||
keybind.chat.name = Chat
|
keybind.chat.name = Chat
|
||||||
@@ -834,6 +845,7 @@ block.junction.name = Junction
|
|||||||
block.router.name = Router
|
block.router.name = Router
|
||||||
block.distributor.name = Distributor
|
block.distributor.name = Distributor
|
||||||
block.sorter.name = Sorter
|
block.sorter.name = Sorter
|
||||||
|
block.inverted-sorter.name = Inverted Sorter
|
||||||
block.message.name = Message
|
block.message.name = Message
|
||||||
block.overflow-gate.name = Overflow Gate
|
block.overflow-gate.name = Overflow Gate
|
||||||
block.silicon-smelter.name = Silicon Smelter
|
block.silicon-smelter.name = Silicon Smelter
|
||||||
@@ -1055,6 +1067,7 @@ block.junction.description = Acts as a bridge for two crossing conveyor belts. U
|
|||||||
block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building.
|
block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building.
|
||||||
block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles.
|
block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles.
|
||||||
block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right.
|
block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right.
|
||||||
|
block.inverted-sorter.descriptions = Processes items like a standard sorter, but outputs selected items to the sides instead.
|
||||||
block.router.description = Accepts items, then outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets.\n\n[scarlet]Never use next to production inputs, as they will get clogged by output.[]
|
block.router.description = Accepts items, then outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets.\n\n[scarlet]Never use next to production inputs, as they will get clogged by output.[]
|
||||||
block.distributor.description = An advanced router. Splits items to up to 7 other directions equally.
|
block.distributor.description = An advanced router. Splits items to up to 7 other directions equally.
|
||||||
block.overflow-gate.description = A combination splitter and router. Only outputs to the left and right if the front path is blocked.
|
block.overflow-gate.description = A combination splitter and router. Only outputs to the left and right if the front path is blocked.
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Celá obrazovka
|
|||||||
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
||||||
setting.fps.name = Ukázat snímky/sekundu
|
setting.fps.name = Ukázat snímky/sekundu
|
||||||
setting.vsync.name = Vertikální synchronizace
|
setting.vsync.name = Vertikální synchronizace
|
||||||
setting.lasers.name = Ukázat laser energie
|
|
||||||
setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance)
|
setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance)
|
||||||
setting.minimap.name = Ukázat minimapu
|
setting.minimap.name = Ukázat minimapu
|
||||||
setting.musicvol.name = Hlasitost hudby
|
setting.musicvol.name = Hlasitost hudby
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Poslat anonymní spis o zhroucení hry
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chat Opacity
|
setting.chatopacity.name = Chat Opacity
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Display In-Game Chat
|
setting.playerchat.name = Display In-Game Chat
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Vollbild
|
|||||||
setting.borderlesswindow.name = Randloses Fenster[LIGHT_GRAY] (Neustart teilweise erforderlich)
|
setting.borderlesswindow.name = Randloses Fenster[LIGHT_GRAY] (Neustart teilweise erforderlich)
|
||||||
setting.fps.name = Zeige FPS
|
setting.fps.name = Zeige FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Zeige Stromlaser
|
|
||||||
setting.pixelate.name = Verpixeln [LIGHT_GRAY](Könnte die Leistung beeinträchtigen)
|
setting.pixelate.name = Verpixeln [LIGHT_GRAY](Könnte die Leistung beeinträchtigen)
|
||||||
setting.minimap.name = Zeige die Minimap
|
setting.minimap.name = Zeige die Minimap
|
||||||
setting.musicvol.name = Musiklautstärke
|
setting.musicvol.name = Musiklautstärke
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Anonyme Absturzberichte senden
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chat Deckkraft
|
setting.chatopacity.name = Chat Deckkraft
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Chat im Spiel anzeigen
|
setting.playerchat.name = Chat im Spiel anzeigen
|
||||||
uiscale.reset = UI-Skalierung wurde geändert.\nDrücke "OK", um diese Skalierung zu bestätigen.\n[scarlet]Zurückkehren und Beenden in[accent] {0}[] Einstellungen...
|
uiscale.reset = UI-Skalierung wurde geändert.\nDrücke "OK", um diese Skalierung zu bestätigen.\n[scarlet]Zurückkehren und Beenden in[accent] {0}[] Einstellungen...
|
||||||
uiscale.cancel = Abbrechen & Beenden
|
uiscale.cancel = Abbrechen & Beenden
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Pantalla Completa
|
|||||||
setting.borderlesswindow.name = Ventana sin Bordes[LIGHT_GRAY] (podría requerir un reinicio)
|
setting.borderlesswindow.name = Ventana sin Bordes[LIGHT_GRAY] (podría requerir un reinicio)
|
||||||
setting.fps.name = Mostrar FPS
|
setting.fps.name = Mostrar FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Mostrar Energía de los Láseres
|
|
||||||
setting.pixelate.name = Pixelar [LIGHT_GRAY](podría reducir el rendimiento)
|
setting.pixelate.name = Pixelar [LIGHT_GRAY](podría reducir el rendimiento)
|
||||||
setting.minimap.name = Mostrar Minimapa
|
setting.minimap.name = Mostrar Minimapa
|
||||||
setting.musicvol.name = Volumen de la Música
|
setting.musicvol.name = Volumen de la Música
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Enviar informes de fallos anónimos
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Opacidad del Chat
|
setting.chatopacity.name = Opacidad del Chat
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Display In-Game Chat
|
setting.playerchat.name = Display In-Game Chat
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Täisekraan
|
|||||||
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
||||||
setting.fps.name = Show FPS
|
setting.fps.name = Show FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Näita Energia Lasereid
|
|
||||||
setting.pixelate.name = Pixelate[LIGHT_GRAY] (disables animations)
|
setting.pixelate.name = Pixelate[LIGHT_GRAY] (disables animations)
|
||||||
setting.minimap.name = Näita Kaarti
|
setting.minimap.name = Näita Kaarti
|
||||||
setting.musicvol.name = Heli tase
|
setting.musicvol.name = Heli tase
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Send Anonymous Crash Reports
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chat Opacity
|
setting.chatopacity.name = Chat Opacity
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Display In-Game Chat
|
setting.playerchat.name = Display In-Game Chat
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Pantaila osoa
|
|||||||
setting.borderlesswindow.name = Ertzik gabeko leihoa[lightgray] (berrabiaraztea behar lezake)
|
setting.borderlesswindow.name = Ertzik gabeko leihoa[lightgray] (berrabiaraztea behar lezake)
|
||||||
setting.fps.name = Erakutsi FPS
|
setting.fps.name = Erakutsi FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Erakutsi energia laserrak
|
|
||||||
setting.pixelate.name = Pixelatu[lightgray] (animazioak desgaitzen ditu)
|
setting.pixelate.name = Pixelatu[lightgray] (animazioak desgaitzen ditu)
|
||||||
setting.minimap.name = Erakutsi mapatxoa
|
setting.minimap.name = Erakutsi mapatxoa
|
||||||
setting.musicvol.name = Musikaren bolumena
|
setting.musicvol.name = Musikaren bolumena
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Bidali kraskatze txosten automatikoak
|
|||||||
setting.savecreate.name = Gorde automatikoki
|
setting.savecreate.name = Gorde automatikoki
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Txataren opakotasuna
|
setting.chatopacity.name = Txataren opakotasuna
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Erakutsi jolas barneko txata
|
setting.playerchat.name = Erakutsi jolas barneko txata
|
||||||
uiscale.reset = Interfazearen eskala aldatu da.\nSakatu "Ados" eskala hau berresteko.\n[scarlet][accent] {0}[] segundo atzera egin eta irteteko...
|
uiscale.reset = Interfazearen eskala aldatu da.\nSakatu "Ados" eskala hau berresteko.\n[scarlet][accent] {0}[] segundo atzera egin eta irteteko...
|
||||||
uiscale.cancel = Utzi eta irten
|
uiscale.cancel = Utzi eta irten
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Plein Écran
|
|||||||
setting.borderlesswindow.name = Fenêtre sans bords (Borderless)[lightgray] (peut requérir le redémarrage du jeu)
|
setting.borderlesswindow.name = Fenêtre sans bords (Borderless)[lightgray] (peut requérir le redémarrage du jeu)
|
||||||
setting.fps.name = Afficher FPS
|
setting.fps.name = Afficher FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Afficher les connections Électriques
|
|
||||||
setting.pixelate.name = Pixeliser[lightgray] (désactive les animations)
|
setting.pixelate.name = Pixeliser[lightgray] (désactive les animations)
|
||||||
setting.minimap.name = Montrer la Minimap
|
setting.minimap.name = Montrer la Minimap
|
||||||
setting.musicvol.name = Volume Musique
|
setting.musicvol.name = Volume Musique
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Envoyer un Rapport de Crash Anonyme
|
|||||||
setting.savecreate.name = Sauvegardes Auto
|
setting.savecreate.name = Sauvegardes Auto
|
||||||
setting.publichost.name = Visibilité de la Partie Publique
|
setting.publichost.name = Visibilité de la Partie Publique
|
||||||
setting.chatopacity.name = Opacité du Chat
|
setting.chatopacity.name = Opacité du Chat
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Montrer le Chat
|
setting.playerchat.name = Montrer le Chat
|
||||||
uiscale.reset = L'échelle de l'interface a été modifiée.\nAppuyez sur "OK" pour confirmer.\n[scarlet]Rétablissement aux parametres d'avant et fermeture dans [accent] {0}[]...
|
uiscale.reset = L'échelle de l'interface a été modifiée.\nAppuyez sur "OK" pour confirmer.\n[scarlet]Rétablissement aux parametres d'avant et fermeture dans [accent] {0}[]...
|
||||||
uiscale.cancel = Annuler & Quitter
|
uiscale.cancel = Annuler & Quitter
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Plein écran
|
|||||||
setting.borderlesswindow.name = Fenêtre sans bordure[LIGHT_GRAY] (peut nécessiter un redémarrage)
|
setting.borderlesswindow.name = Fenêtre sans bordure[LIGHT_GRAY] (peut nécessiter un redémarrage)
|
||||||
setting.fps.name = Afficher FPS
|
setting.fps.name = Afficher FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Afficher les rayons des lasers
|
|
||||||
setting.pixelate.name = Pixélisé [LIGHT_GRAY](peut diminuer les performances)[]
|
setting.pixelate.name = Pixélisé [LIGHT_GRAY](peut diminuer les performances)[]
|
||||||
setting.minimap.name = Montrer la minimap
|
setting.minimap.name = Montrer la minimap
|
||||||
setting.musicvol.name = Volume de la musique
|
setting.musicvol.name = Volume de la musique
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Envoyer des rapports d'incident anonymement.
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Opacité du tchat
|
setting.chatopacity.name = Opacité du tchat
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Afficher le tchat en jeu
|
setting.playerchat.name = Afficher le tchat en jeu
|
||||||
uiscale.reset = L'échelle de l'interface a été modifiée.\nAppuyez sur "OK" pour confirmer cette échelle.\n[scarlet]Revenir et sortir en[accent] {0}[] réglages...
|
uiscale.reset = L'échelle de l'interface a été modifiée.\nAppuyez sur "OK" pour confirmer cette échelle.\n[scarlet]Revenir et sortir en[accent] {0}[] réglages...
|
||||||
uiscale.cancel = Annuler et quitter
|
uiscale.cancel = Annuler et quitter
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Layar Penuh
|
|||||||
setting.borderlesswindow.name = Jendela tak Berbatas[LIGHT_GRAY] (bisa membutuhkan restart)
|
setting.borderlesswindow.name = Jendela tak Berbatas[LIGHT_GRAY] (bisa membutuhkan restart)
|
||||||
setting.fps.name = Tunjukkan FPS
|
setting.fps.name = Tunjukkan FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Tunjukkan Laser
|
|
||||||
setting.pixelate.name = Mode Pixel[LIGHT_GRAY] (menonaktifkan animasi)
|
setting.pixelate.name = Mode Pixel[LIGHT_GRAY] (menonaktifkan animasi)
|
||||||
setting.minimap.name = Tunjukkan Peta kecil
|
setting.minimap.name = Tunjukkan Peta kecil
|
||||||
setting.musicvol.name = Volume Musik
|
setting.musicvol.name = Volume Musik
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Laporkan Masalah
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Jelas-Beningnya Chat
|
setting.chatopacity.name = Jelas-Beningnya Chat
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Tunjukkan Chat dalam Permainan
|
setting.playerchat.name = Tunjukkan Chat dalam Permainan
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Schermo Intero
|
|||||||
setting.borderlesswindow.name = Schermo senza bordi[LIGHT_GRAY] (potrebbe richiedere riapertura gioco)
|
setting.borderlesswindow.name = Schermo senza bordi[LIGHT_GRAY] (potrebbe richiedere riapertura gioco)
|
||||||
setting.fps.name = Mostra FPS
|
setting.fps.name = Mostra FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Mostra Laser Energetici
|
|
||||||
setting.pixelate.name = Sfocare [LIGHT_GRAY](potrebbe ridure il rendimento)
|
setting.pixelate.name = Sfocare [LIGHT_GRAY](potrebbe ridure il rendimento)
|
||||||
setting.minimap.name = Mostra minimappa
|
setting.minimap.name = Mostra minimappa
|
||||||
setting.musicvol.name = Volume Musica
|
setting.musicvol.name = Volume Musica
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Invia rapporti sugli arresti anomali anonimamente
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Opacità chat
|
setting.chatopacity.name = Opacità chat
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Mostra Chat in-game
|
setting.playerchat.name = Mostra Chat in-game
|
||||||
uiscale.reset = La scala dell'interfaccia utente è stata modificata.\nPremere "OK" per confermare questa scala.\n[scarlet] Ripristina ed esci dalle impostazioni [accent] {0}[] impostazioni...
|
uiscale.reset = La scala dell'interfaccia utente è stata modificata.\nPremere "OK" per confermare questa scala.\n[scarlet] Ripristina ed esci dalle impostazioni [accent] {0}[] impostazioni...
|
||||||
uiscale.cancel = Annulla ed esci
|
uiscale.cancel = Annulla ed esci
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = フルスクリーン
|
|||||||
setting.borderlesswindow.name = 境界の無いウィンドウ[lightgray] (再起動が必要になる場合があります)
|
setting.borderlesswindow.name = 境界の無いウィンドウ[lightgray] (再起動が必要になる場合があります)
|
||||||
setting.fps.name = FPSを表示
|
setting.fps.name = FPSを表示
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = 電力線を表示
|
|
||||||
setting.pixelate.name = ピクセル化[lightgray] (アニメーションが無効化されます)
|
setting.pixelate.name = ピクセル化[lightgray] (アニメーションが無効化されます)
|
||||||
setting.minimap.name = ミニマップを表示
|
setting.minimap.name = ミニマップを表示
|
||||||
setting.musicvol.name = 音楽 音量
|
setting.musicvol.name = 音楽 音量
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = 匿名でクラッシュレポートを送信する
|
|||||||
setting.savecreate.name = 自動保存
|
setting.savecreate.name = 自動保存
|
||||||
setting.publichost.name = 誰でもゲームに参加できるようにする
|
setting.publichost.name = 誰でもゲームに参加できるようにする
|
||||||
setting.chatopacity.name = チャットの透明度
|
setting.chatopacity.name = チャットの透明度
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = ゲーム内にチャットを表示
|
setting.playerchat.name = ゲーム内にチャットを表示
|
||||||
uiscale.reset = UIサイズが変更されました。\nこのままでよければ「OK」を押してください。\n[scarlet][accent]{0}[] 秒で元の設定に戻ります...
|
uiscale.reset = UIサイズが変更されました。\nこのままでよければ「OK」を押してください。\n[scarlet][accent]{0}[] 秒で元の設定に戻ります...
|
||||||
uiscale.cancel = キャンセル & 終了
|
uiscale.cancel = キャンセル & 終了
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = 전체 화면
|
|||||||
setting.borderlesswindow.name = 테두리 없는 창모드[LIGHT_GRAY] (재시작이 필요할 수 있습니다)
|
setting.borderlesswindow.name = 테두리 없는 창모드[LIGHT_GRAY] (재시작이 필요할 수 있습니다)
|
||||||
setting.fps.name = FPS 표시
|
setting.fps.name = FPS 표시
|
||||||
setting.vsync.name = VSync 활성화
|
setting.vsync.name = VSync 활성화
|
||||||
setting.lasers.name = 전력 노드 레이저 표시
|
|
||||||
setting.pixelate.name = 픽셀화[LIGHT_GRAY] (애니메이션 효과가 꺼집니다)
|
setting.pixelate.name = 픽셀화[LIGHT_GRAY] (애니메이션 효과가 꺼집니다)
|
||||||
setting.minimap.name = 미니맵 보기
|
setting.minimap.name = 미니맵 보기
|
||||||
setting.musicvol.name = 음악 크기
|
setting.musicvol.name = 음악 크기
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = 오류 보고서 보내기
|
|||||||
setting.savecreate.name = 자동 저장 활성화
|
setting.savecreate.name = 자동 저장 활성화
|
||||||
setting.publichost.name = 공용 서버 보이기
|
setting.publichost.name = 공용 서버 보이기
|
||||||
setting.chatopacity.name = 채팅 투명도
|
setting.chatopacity.name = 채팅 투명도
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = 인게임 채팅 표시
|
setting.playerchat.name = 인게임 채팅 표시
|
||||||
uiscale.reset = UI 스케일이 변경되었습니다.\n"확인"버튼을 눌러 스케일을 확인하세요.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
uiscale.reset = UI 스케일이 변경되었습니다.\n"확인"버튼을 눌러 스케일을 확인하세요.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
||||||
uiscale.cancel = 취소 & 나가기
|
uiscale.cancel = 취소 & 나가기
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Fullscreen
|
|||||||
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
||||||
setting.fps.name = Show FPS
|
setting.fps.name = Show FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Show Power Lasers
|
|
||||||
setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance)
|
setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance)
|
||||||
setting.minimap.name = Show Minimap
|
setting.minimap.name = Show Minimap
|
||||||
setting.musicvol.name = Music Volume
|
setting.musicvol.name = Music Volume
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Send Anonymous Crash Reports
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chat Opacity
|
setting.chatopacity.name = Chat Opacity
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Display In-Game Chat
|
setting.playerchat.name = Display In-Game Chat
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Fullscreen
|
|||||||
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
||||||
setting.fps.name = Show FPS
|
setting.fps.name = Show FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Show Power Lasers
|
|
||||||
setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance, disables animations)
|
setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance, disables animations)
|
||||||
setting.minimap.name = Show Minimap
|
setting.minimap.name = Show Minimap
|
||||||
setting.musicvol.name = Music Volume
|
setting.musicvol.name = Music Volume
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Send Anonymous Crash Reports
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chat Opacity
|
setting.chatopacity.name = Chat Opacity
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Display In-Game Chat
|
setting.playerchat.name = Display In-Game Chat
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Pełny ekran
|
|||||||
setting.borderlesswindow.name = Bezramkowe okno[LIGHT_GRAY] (może wymagać restartu)
|
setting.borderlesswindow.name = Bezramkowe okno[LIGHT_GRAY] (może wymagać restartu)
|
||||||
setting.fps.name = Pokazuj FPS
|
setting.fps.name = Pokazuj FPS
|
||||||
setting.vsync.name = Synchronizacja pionowa
|
setting.vsync.name = Synchronizacja pionowa
|
||||||
setting.lasers.name = Pokaż lasery zasilające
|
|
||||||
setting.pixelate.name = Pikselacja [LIGHT_GRAY](wyłącza animacje)
|
setting.pixelate.name = Pikselacja [LIGHT_GRAY](wyłącza animacje)
|
||||||
setting.minimap.name = Pokaż Minimapę
|
setting.minimap.name = Pokaż Minimapę
|
||||||
setting.musicvol.name = Głośność muzyki
|
setting.musicvol.name = Głośność muzyki
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Wysyłaj anonimowo dane o crashu gry
|
|||||||
setting.savecreate.name = Automatyczne tworzenie zapisu
|
setting.savecreate.name = Automatyczne tworzenie zapisu
|
||||||
setting.publichost.name = Widoczność gry publicznej
|
setting.publichost.name = Widoczność gry publicznej
|
||||||
setting.chatopacity.name = Przezroczystość czatu
|
setting.chatopacity.name = Przezroczystość czatu
|
||||||
|
setting.lasersopacity.name = Przezroczystość laserów zasilających
|
||||||
setting.playerchat.name = Wyświetlaj czat w grze
|
setting.playerchat.name = Wyświetlaj czat w grze
|
||||||
uiscale.reset = Skala interfejsu uległa zmianie.\nNaciśnij "OK" by potwierdzić zmiany.\n[scarlet]Cofanie zmian i wyjście z gry za[accent] {0}[]
|
uiscale.reset = Skala interfejsu uległa zmianie.\nNaciśnij "OK" by potwierdzić zmiany.\n[scarlet]Cofanie zmian i wyjście z gry za[accent] {0}[]
|
||||||
uiscale.cancel = Anuluj i wyjdź
|
uiscale.cancel = Anuluj i wyjdź
|
||||||
|
|||||||
@@ -560,7 +560,6 @@ setting.fullscreen.name = Tela Cheia
|
|||||||
setting.borderlesswindow.name = Janela sem borda[LIGHT_GRAY] (Pode precisar reiniciar)
|
setting.borderlesswindow.name = Janela sem borda[LIGHT_GRAY] (Pode precisar reiniciar)
|
||||||
setting.fps.name = Mostrar FPS
|
setting.fps.name = Mostrar FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Mostrar lasers
|
|
||||||
setting.pixelate.name = Pixelizado [LIGHT_GRAY](Pode diminuir a performace)
|
setting.pixelate.name = Pixelizado [LIGHT_GRAY](Pode diminuir a performace)
|
||||||
setting.minimap.name = Mostrar minimapa
|
setting.minimap.name = Mostrar minimapa
|
||||||
setting.musicvol.name = Volume da Música
|
setting.musicvol.name = Volume da Música
|
||||||
@@ -572,6 +571,7 @@ setting.crashreport.name = Enviar denuncias de crash anonimas
|
|||||||
setting.savecreate.name = Criar salvamentos automaticamente
|
setting.savecreate.name = Criar salvamentos automaticamente
|
||||||
setting.publichost.name = Visibilidade do jogo público
|
setting.publichost.name = Visibilidade do jogo público
|
||||||
setting.chatopacity.name = Opacidade do chat
|
setting.chatopacity.name = Opacidade do chat
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Mostrar chat em jogo
|
setting.playerchat.name = Mostrar chat em jogo
|
||||||
uiscale.reset = A escala da IU foi mudada.\nPressione "OK" para confirmar esta escala.\n[scarlet]Revertendo e saindo em[accent] {0}[] settings...
|
uiscale.reset = A escala da IU foi mudada.\nPressione "OK" para confirmar esta escala.\n[scarlet]Revertendo e saindo em[accent] {0}[] settings...
|
||||||
uiscale.cancel = Cancelar e sair
|
uiscale.cancel = Cancelar e sair
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Полноэкранный режим
|
|||||||
setting.borderlesswindow.name = Безрамочное окно[lightgray] (может потребоваться перезапуск)
|
setting.borderlesswindow.name = Безрамочное окно[lightgray] (может потребоваться перезапуск)
|
||||||
setting.fps.name = Показывать FPS
|
setting.fps.name = Показывать FPS
|
||||||
setting.vsync.name = Вертикальная синхронизация
|
setting.vsync.name = Вертикальная синхронизация
|
||||||
setting.lasers.name = Показывать лазеры энергоснабжения
|
|
||||||
setting.pixelate.name = Пикселизация[lightgray] (отключает анимации)
|
setting.pixelate.name = Пикселизация[lightgray] (отключает анимации)
|
||||||
setting.minimap.name = Показать миникарту
|
setting.minimap.name = Показать миникарту
|
||||||
setting.musicvol.name = Громкость музыки
|
setting.musicvol.name = Громкость музыки
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Отправлять анонимные отчёты
|
|||||||
setting.savecreate.name = Автоматическое создание сохранений
|
setting.savecreate.name = Автоматическое создание сохранений
|
||||||
setting.publichost.name = Общедоступность игры
|
setting.publichost.name = Общедоступность игры
|
||||||
setting.chatopacity.name = Непрозрачность чата
|
setting.chatopacity.name = Непрозрачность чата
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Отображать облака чата над игроками
|
setting.playerchat.name = Отображать облака чата над игроками
|
||||||
uiscale.reset = Масштаб пользовательского интерфейса был изменён.\nНажмите «ОК» для подтверждения этого масштаба.\n[scarlet]Возврат настроек и выход через[accent] {0}[] секунд…
|
uiscale.reset = Масштаб пользовательского интерфейса был изменён.\nНажмите «ОК» для подтверждения этого масштаба.\n[scarlet]Возврат настроек и выход через[accent] {0}[] секунд…
|
||||||
uiscale.cancel = Отменить & Выйти
|
uiscale.cancel = Отменить & Выйти
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Fullskärm
|
|||||||
setting.borderlesswindow.name = Borderless Window[lightgray] (may require restart)
|
setting.borderlesswindow.name = Borderless Window[lightgray] (may require restart)
|
||||||
setting.fps.name = Show FPS
|
setting.fps.name = Show FPS
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Show Power Lasers
|
|
||||||
setting.pixelate.name = Pixellera[lightgray] (disables animations)
|
setting.pixelate.name = Pixellera[lightgray] (disables animations)
|
||||||
setting.minimap.name = Visa Minikarta
|
setting.minimap.name = Visa Minikarta
|
||||||
setting.musicvol.name = Musikvolym
|
setting.musicvol.name = Musikvolym
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Skicka Anonyma Krashrapporter
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chattgenomskinlighet
|
setting.chatopacity.name = Chattgenomskinlighet
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Visa Chatt
|
setting.playerchat.name = Visa Chatt
|
||||||
uiscale.reset = UI-skalan har ändrats.\nTryck "OK" för att använda den här skalan.\n[scarlet]Avslutar och återställer om[accent] {0}[] sekunder...
|
uiscale.reset = UI-skalan har ändrats.\nTryck "OK" för att använda den här skalan.\n[scarlet]Avslutar och återställer om[accent] {0}[] sekunder...
|
||||||
uiscale.cancel = Avbryt och Avsluta
|
uiscale.cancel = Avbryt och Avsluta
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = Tam ekran
|
|||||||
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart)
|
||||||
setting.fps.name = FPS'i goster
|
setting.fps.name = FPS'i goster
|
||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Guc lazerlerini goster
|
|
||||||
setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance)
|
setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance)
|
||||||
setting.minimap.name = Haritayi goster
|
setting.minimap.name = Haritayi goster
|
||||||
setting.musicvol.name = Ses yuksekligi
|
setting.musicvol.name = Ses yuksekligi
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = Send Anonymous Crash Reports
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chat Opacity
|
setting.chatopacity.name = Chat Opacity
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Display In-Game Chat
|
setting.playerchat.name = Display In-Game Chat
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
|
|||||||
@@ -562,19 +562,20 @@ setting.fps.name = FPS Göster
|
|||||||
setting.vsync.name = VSync
|
setting.vsync.name = VSync
|
||||||
setting.lasers.name = Enerji Işınlarını Göster
|
setting.lasers.name = Enerji Işınlarını Göster
|
||||||
setting.pixelate.name = Pixelle[lightgray] (animasyonları kapatır)
|
setting.pixelate.name = Pixelle[lightgray] (animasyonları kapatır)
|
||||||
setting.minimap.name = Show Minimap
|
setting.minimap.name = Harita Göster
|
||||||
setting.musicvol.name = Music Volume
|
setting.musicvol.name = Müzik
|
||||||
setting.ambientvol.name = Ambient Volume
|
setting.ambientvol.name = Etraf Sesi
|
||||||
setting.mutemusic.name = Mute Music
|
setting.mutemusic.name = Müziği Kapat
|
||||||
setting.sfxvol.name = SFX Volume
|
setting.sfxvol.name = Oyun Sesi
|
||||||
setting.mutesound.name = Mute Sound
|
setting.mutesound.name = Sesi Kapat
|
||||||
setting.crashreport.name = Send Anonymous Crash Reports
|
setting.crashreport.name = Send Anonymous Crash Reports
|
||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = Chat Opacity
|
setting.chatopacity.name = Chat Opacity
|
||||||
setting.playerchat.name = Display Player Bubble Chat
|
setting.lasersopacity.name = Enerji Lazeri Opaklığı
|
||||||
|
setting.playerchat.name = Oyun-içi Konuşmayı Göster
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = İptal Et ve Çık
|
||||||
setting.bloom.name = Bloom
|
setting.bloom.name = Bloom
|
||||||
keybind.title = Rebind Keys
|
keybind.title = Rebind Keys
|
||||||
keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only basic movement is supported.
|
keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only basic movement is supported.
|
||||||
|
|||||||
@@ -551,7 +551,6 @@ setting.fullscreen.name = Повноекранний режим
|
|||||||
setting.borderlesswindow.name = Вікно без полів[lightgray] (може потребувати перезапуску)
|
setting.borderlesswindow.name = Вікно без полів[lightgray] (може потребувати перезапуску)
|
||||||
setting.fps.name = Показувати FPS
|
setting.fps.name = Показувати FPS
|
||||||
setting.vsync.name = Вертикальна синхронізація
|
setting.vsync.name = Вертикальна синхронізація
|
||||||
setting.lasers.name = Показувати енергію лазерів
|
|
||||||
setting.pixelate.name = Пікселізація[lightgray] (вимикає анімації)
|
setting.pixelate.name = Пікселізація[lightgray] (вимикає анімації)
|
||||||
setting.minimap.name = Показувати міні-мапу
|
setting.minimap.name = Показувати міні-мапу
|
||||||
setting.musicvol.name = Гучність музики
|
setting.musicvol.name = Гучність музики
|
||||||
@@ -563,6 +562,7 @@ setting.crashreport.name = Відсилати анонімні звіти про
|
|||||||
setting.savecreate.name = Автоматичне створення збережень
|
setting.savecreate.name = Автоматичне створення збережень
|
||||||
setting.publichost.name = Загальнодоступність гри
|
setting.publichost.name = Загальнодоступність гри
|
||||||
setting.chatopacity.name = Непрозорість чату
|
setting.chatopacity.name = Непрозорість чату
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = Відображати хмару чата над гравцями
|
setting.playerchat.name = Відображати хмару чата над гравцями
|
||||||
public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[lightgray]Це можна змінити у Налаштування->Гра->Public Game Visibility.
|
public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[lightgray]Це можна змінити у Налаштування->Гра->Public Game Visibility.
|
||||||
uiscale.reset = Масштаб користувальницького інтерфейсу було змінено.\nНатисніть «ОК» для підтверждення цього масшатабу.\n[scarlet]Повернення налаштувань і вихід через[accent] {0}[] …
|
uiscale.reset = Масштаб користувальницького інтерфейсу було змінено.\nНатисніть «ОК» для підтверждення цього масшатабу.\n[scarlet]Повернення налаштувань і вихід через[accent] {0}[] …
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = 全屏
|
|||||||
setting.borderlesswindow.name = 无边框窗口[LIGHT_GRAY] (可能需要重启)
|
setting.borderlesswindow.name = 无边框窗口[LIGHT_GRAY] (可能需要重启)
|
||||||
setting.fps.name = 显示 FPS
|
setting.fps.name = 显示 FPS
|
||||||
setting.vsync.name = 垂直同步
|
setting.vsync.name = 垂直同步
|
||||||
setting.lasers.name = 显示能量射线
|
|
||||||
setting.pixelate.name = 像素画面 [LIGHT_GRAY](禁用动画)
|
setting.pixelate.name = 像素画面 [LIGHT_GRAY](禁用动画)
|
||||||
setting.minimap.name = 显示小地图
|
setting.minimap.name = 显示小地图
|
||||||
setting.musicvol.name = 音乐音量
|
setting.musicvol.name = 音乐音量
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = 发送匿名崩溃报告
|
|||||||
setting.savecreate.name = 自动创建存档
|
setting.savecreate.name = 自动创建存档
|
||||||
setting.publichost.name = 公共游戏旁观
|
setting.publichost.name = 公共游戏旁观
|
||||||
setting.chatopacity.name = 聊天界面透明度
|
setting.chatopacity.name = 聊天界面透明度
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = 显示游戏内聊天界面
|
setting.playerchat.name = 显示游戏内聊天界面
|
||||||
uiscale.reset = UI缩放比例已经改变。\n按下“确定”来确定缩放比例\n[accent]{0}[]秒后[scarlet]退出并恢复设定。
|
uiscale.reset = UI缩放比例已经改变。\n按下“确定”来确定缩放比例\n[accent]{0}[]秒后[scarlet]退出并恢复设定。
|
||||||
uiscale.cancel = 取消并退出
|
uiscale.cancel = 取消并退出
|
||||||
|
|||||||
@@ -545,7 +545,6 @@ setting.fullscreen.name = 全螢幕
|
|||||||
setting.borderlesswindow.name = 無邊框窗口[LIGHT_GRAY](可能需要重啟)
|
setting.borderlesswindow.name = 無邊框窗口[LIGHT_GRAY](可能需要重啟)
|
||||||
setting.fps.name = 顯示FPS
|
setting.fps.name = 顯示FPS
|
||||||
setting.vsync.name = 垂直同步
|
setting.vsync.name = 垂直同步
|
||||||
setting.lasers.name = 顯示雷射光束
|
|
||||||
setting.pixelate.name = 像素化[LIGHT_GRAY](可能降低性能)
|
setting.pixelate.name = 像素化[LIGHT_GRAY](可能降低性能)
|
||||||
setting.minimap.name = 顯示小地圖
|
setting.minimap.name = 顯示小地圖
|
||||||
setting.musicvol.name = 音樂音量
|
setting.musicvol.name = 音樂音量
|
||||||
@@ -557,6 +556,7 @@ setting.crashreport.name = 發送匿名崩潰報告
|
|||||||
setting.savecreate.name = Auto-Create Saves
|
setting.savecreate.name = Auto-Create Saves
|
||||||
setting.publichost.name = Public Game Visibility
|
setting.publichost.name = Public Game Visibility
|
||||||
setting.chatopacity.name = 聊天框不透明度
|
setting.chatopacity.name = 聊天框不透明度
|
||||||
|
setting.lasersopacity.name = Power Laser Opacity
|
||||||
setting.playerchat.name = 在遊戲中顯示聊天框
|
setting.playerchat.name = 在遊戲中顯示聊天框
|
||||||
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings...
|
||||||
uiscale.cancel = Cancel & Exit
|
uiscale.cancel = Cancel & Exit
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 725 B After Width: | Height: | Size: 727 B |
|
Before Width: | Height: | Size: 712 KiB After Width: | Height: | Size: 712 KiB |
|
Before Width: | Height: | Size: 259 KiB After Width: | Height: | Size: 259 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 893 KiB |
|
Before Width: | Height: | Size: 721 KiB After Width: | Height: | Size: 134 KiB |
@@ -47,6 +47,8 @@ public class Vars implements Loadable{
|
|||||||
public static final String crashReportURL = "http://mins.us.to/report";
|
public static final String crashReportURL = "http://mins.us.to/report";
|
||||||
/** URL the links to the wiki's modding guide.*/
|
/** URL the links to the wiki's modding guide.*/
|
||||||
public static final String modGuideURL = "https://mindustrygame.github.io/wiki/modding/";
|
public static final String modGuideURL = "https://mindustrygame.github.io/wiki/modding/";
|
||||||
|
/** URL the links to the wiki's modding guide.*/
|
||||||
|
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?template=bug_report.md";
|
||||||
/** list of built-in servers.*/
|
/** list of built-in servers.*/
|
||||||
public static final Array<String> defaultServers = Array.with(/*"mins.us.to"*/);
|
public static final Array<String> defaultServers = Array.with(/*"mins.us.to"*/);
|
||||||
/** maximum distance between mine and core that supports automatic transferring */
|
/** maximum distance between mine and core that supports automatic transferring */
|
||||||
@@ -259,7 +261,7 @@ public class Vars implements Loadable{
|
|||||||
public static void loadSettings(){
|
public static void loadSettings(){
|
||||||
Core.settings.setAppName(appName);
|
Core.settings.setAppName(appName);
|
||||||
|
|
||||||
if(steam || "steam".equals(Version.modifier)){
|
if(steam || (Version.modifier != null && Version.modifier.contains("steam"))){
|
||||||
Core.settings.setDataDirectory(Core.files.local("saves/"));
|
Core.settings.setDataDirectory(Core.files.local("saves/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class Blocks implements ContentList{
|
|||||||
phaseWall, phaseWallLarge, surgeWall, surgeWallLarge, mender, mendProjector, overdriveProjector, forceProjector, shockMine,
|
phaseWall, phaseWallLarge, surgeWall, surgeWallLarge, mender, mendProjector, overdriveProjector, forceProjector, shockMine,
|
||||||
|
|
||||||
//transport
|
//transport
|
||||||
conveyor, titaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, router, overflowGate, massDriver,
|
conveyor, titaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router, overflowGate, massDriver,
|
||||||
|
|
||||||
//liquids
|
//liquids
|
||||||
mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit,
|
mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit,
|
||||||
@@ -935,7 +935,11 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
sorter = new Sorter("sorter"){{
|
sorter = new Sorter("sorter"){{
|
||||||
requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 2));
|
requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 2));
|
||||||
|
}};
|
||||||
|
|
||||||
|
invertedSorter = new Sorter("inverted-sorter"){{
|
||||||
|
requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 2));
|
||||||
|
invert = true;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
router = new Router("router"){{
|
router = new Router("router"){{
|
||||||
@@ -965,12 +969,12 @@ public class Blocks implements ContentList{
|
|||||||
//region liquid
|
//region liquid
|
||||||
|
|
||||||
mechanicalPump = new Pump("mechanical-pump"){{
|
mechanicalPump = new Pump("mechanical-pump"){{
|
||||||
requirements(Category.liquid, ItemStack.with(Items.copper, 15, Items.lead, 10));
|
requirements(Category.liquid, ItemStack.with(Items.copper, 15, Items.metaglass, 10));
|
||||||
pumpAmount = 0.1f;
|
pumpAmount = 0.1f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
rotaryPump = new Pump("rotary-pump"){{
|
rotaryPump = new Pump("rotary-pump"){{
|
||||||
requirements(Category.liquid, ItemStack.with(Items.copper, 70, Items.lead, 50, Items.silicon, 20, Items.titanium, 35));
|
requirements(Category.liquid, ItemStack.with(Items.copper, 70, Items.metaglass, 50, Items.silicon, 20, Items.titanium, 35));
|
||||||
pumpAmount = 0.8f;
|
pumpAmount = 0.8f;
|
||||||
consumes.power(0.15f);
|
consumes.power(0.15f);
|
||||||
liquidCapacity = 30f;
|
liquidCapacity = 30f;
|
||||||
@@ -979,7 +983,7 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
thermalPump = new Pump("thermal-pump"){{
|
thermalPump = new Pump("thermal-pump"){{
|
||||||
requirements(Category.liquid, ItemStack.with(Items.copper, 80, Items.lead, 65, Items.silicon, 30, Items.titanium, 40, Items.thorium, 35));
|
requirements(Category.liquid, ItemStack.with(Items.copper, 80, Items.metaglass, 70, Items.silicon, 30, Items.titanium, 40, Items.thorium, 35));
|
||||||
pumpAmount = 1.5f;
|
pumpAmount = 1.5f;
|
||||||
consumes.power(0.30f);
|
consumes.power(0.30f);
|
||||||
liquidCapacity = 40f;
|
liquidCapacity = 40f;
|
||||||
@@ -993,13 +997,13 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
pulseConduit = new Conduit("pulse-conduit"){{
|
pulseConduit = new Conduit("pulse-conduit"){{
|
||||||
requirements(Category.liquid, ItemStack.with(Items.titanium, 1, Items.metaglass, 1));
|
requirements(Category.liquid, ItemStack.with(Items.titanium, 2, Items.metaglass, 1));
|
||||||
liquidCapacity = 16f;
|
liquidCapacity = 16f;
|
||||||
health = 90;
|
health = 90;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
liquidRouter = new LiquidRouter("liquid-router"){{
|
liquidRouter = new LiquidRouter("liquid-router"){{
|
||||||
requirements(Category.liquid, ItemStack.with(Items.titanium, 2, Items.metaglass, 2));
|
requirements(Category.liquid, ItemStack.with(Items.graphite, 4, Items.metaglass, 2));
|
||||||
liquidCapacity = 20f;
|
liquidCapacity = 20f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -1011,11 +1015,11 @@ public class Blocks implements ContentList{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
liquidJunction = new LiquidJunction("liquid-junction"){{
|
liquidJunction = new LiquidJunction("liquid-junction"){{
|
||||||
requirements(Category.liquid, ItemStack.with(Items.titanium, 2, Items.metaglass, 2));
|
requirements(Category.liquid, ItemStack.with(Items.graphite, 2, Items.metaglass, 2));
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{
|
bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{
|
||||||
requirements(Category.liquid, ItemStack.with(Items.titanium, 4, Items.metaglass, 4));
|
requirements(Category.liquid, ItemStack.with(Items.graphite, 4, Items.metaglass, 8));
|
||||||
range = 4;
|
range = 4;
|
||||||
hasPower = false;
|
hasPower = false;
|
||||||
}};
|
}};
|
||||||
@@ -1083,11 +1087,12 @@ public class Blocks implements ContentList{
|
|||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
differentialGenerator = new SingleTypeGenerator(true, false, "differential-generator"){{
|
differentialGenerator = new SingleTypeGenerator("differential-generator"){{
|
||||||
requirements(Category.power, ItemStack.with(Items.copper, 70, Items.titanium, 50, Items.lead, 100, Items.silicon, 65, Items.metaglass, 50));
|
requirements(Category.power, ItemStack.with(Items.copper, 70, Items.titanium, 50, Items.lead, 100, Items.silicon, 65, Items.metaglass, 50));
|
||||||
powerProduction = 16f;
|
powerProduction = 16f;
|
||||||
itemDuration = 120f;
|
itemDuration = 120f;
|
||||||
hasLiquids = true;
|
hasLiquids = true;
|
||||||
|
hasItems = true;
|
||||||
size = 3;
|
size = 3;
|
||||||
|
|
||||||
consumes.item(Items.pyratite).optional(true, false);
|
consumes.item(Items.pyratite).optional(true, false);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public class TechTree implements ContentList{
|
|||||||
|
|
||||||
node(distributor);
|
node(distributor);
|
||||||
node(sorter, () -> {
|
node(sorter, () -> {
|
||||||
|
node(invertedSorter);
|
||||||
node(message);
|
node(message);
|
||||||
node(overflowGate);
|
node(overflowGate);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class UnitTypes implements ContentList{
|
|||||||
range = 70f;
|
range = 70f;
|
||||||
itemCapacity = 70;
|
itemCapacity = 70;
|
||||||
health = 400;
|
health = 400;
|
||||||
buildPower = 1f;
|
buildPower = 0.4f;
|
||||||
engineOffset = 6.5f;
|
engineOffset = 6.5f;
|
||||||
toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium);
|
toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium);
|
||||||
weapon = new Weapon("heal-blaster"){{
|
weapon = new Weapon("heal-blaster"){{
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
package io.anuke.mindustry.content;
|
package io.anuke.mindustry.content;
|
||||||
|
|
||||||
import io.anuke.arc.collection.Array;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.game.ContentList;
|
import io.anuke.mindustry.game.Objectives.*;
|
||||||
import io.anuke.mindustry.game.SpawnGroup;
|
import io.anuke.mindustry.maps.generators.*;
|
||||||
import io.anuke.mindustry.maps.generators.MapGenerator;
|
import io.anuke.mindustry.maps.generators.MapGenerator.*;
|
||||||
import io.anuke.mindustry.maps.generators.MapGenerator.Decoration;
|
import io.anuke.mindustry.maps.zonegen.*;
|
||||||
import io.anuke.mindustry.maps.zonegen.DesertWastesGenerator;
|
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.world.Block;
|
|
||||||
|
import static io.anuke.arc.collection.Array.with;
|
||||||
|
import static io.anuke.mindustry.content.Items.*;
|
||||||
|
import static io.anuke.mindustry.type.ItemStack.list;
|
||||||
|
|
||||||
public class Zones implements ContentList{
|
public class Zones implements ContentList{
|
||||||
public static Zone
|
public static Zone
|
||||||
@@ -20,28 +22,26 @@ public class Zones implements ContentList{
|
|||||||
public void load(){
|
public void load(){
|
||||||
|
|
||||||
groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1)){{
|
groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1)){{
|
||||||
baseLaunchCost = ItemStack.with(Items.copper, -60);
|
baseLaunchCost = list(copper, -60);
|
||||||
startingItems = ItemStack.list(Items.copper, 60);
|
startingItems = list(copper, 60);
|
||||||
alwaysUnlocked = true;
|
alwaysUnlocked = true;
|
||||||
conditionWave = 5;
|
conditionWave = 5;
|
||||||
launchPeriod = 5;
|
launchPeriod = 5;
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead};
|
resources = with(copper, scrap, lead);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
desertWastes = new Zone("desertWastes", new DesertWastesGenerator(260, 260)){{
|
desertWastes = new Zone("desertWastes", new DesertWastesGenerator(260, 260)){{
|
||||||
startingItems = ItemStack.list(Items.copper, 120);
|
startingItems = list(copper, 120);
|
||||||
conditionWave = 20;
|
conditionWave = 20;
|
||||||
launchPeriod = 10;
|
launchPeriod = 10;
|
||||||
loadout = Loadouts.advancedShard;
|
loadout = Loadouts.advancedShard;
|
||||||
zoneRequirements = ZoneRequirement.with(groundZero, 20);
|
resources = with(copper, lead, coal, sand);
|
||||||
blockRequirements = new Block[]{Blocks.combustionGenerator};
|
|
||||||
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.sand};
|
|
||||||
rules = r -> {
|
rules = r -> {
|
||||||
r.waves = true;
|
r.waves = true;
|
||||||
r.waveTimer = true;
|
r.waveTimer = true;
|
||||||
r.launchWaveMultiplier = 3f;
|
r.launchWaveMultiplier = 3f;
|
||||||
r.waveSpacing = 60 * 50f;
|
r.waveSpacing = 60 * 50f;
|
||||||
r.spawns = Array.with(
|
r.spawns = with(
|
||||||
new SpawnGroup(UnitTypes.crawler){{
|
new SpawnGroup(UnitTypes.crawler){{
|
||||||
unitScaling = 3f;
|
unitScaling = 3f;
|
||||||
}},
|
}},
|
||||||
@@ -75,96 +75,140 @@ public class Zones implements ContentList{
|
|||||||
}}
|
}}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
requirements = with(
|
||||||
|
new ZoneWave(groundZero, 20),
|
||||||
|
new Unlock(Blocks.combustionGenerator)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
saltFlats = new Zone("saltFlats", new MapGenerator("saltFlats")){{
|
saltFlats = new Zone("saltFlats", new MapGenerator("saltFlats")){{
|
||||||
startingItems = ItemStack.list(Items.copper, 200, Items.silicon, 200, Items.lead, 200);
|
startingItems = list(copper, 200, Items.silicon, 200, lead, 200);
|
||||||
loadout = Loadouts.basicFoundation;
|
loadout = Loadouts.basicFoundation;
|
||||||
conditionWave = 10;
|
conditionWave = 10;
|
||||||
launchPeriod = 5;
|
launchPeriod = 5;
|
||||||
zoneRequirements = ZoneRequirement.with(desertWastes, 60);
|
configureObjective = new Launched(this);
|
||||||
blockRequirements = new Block[]{Blocks.daggerFactory, Blocks.draugFactory, Blocks.door, Blocks.waterExtractor};
|
resources = with(copper, scrap, lead, coal, sand, titanium);
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand, Items.titanium};
|
requirements = with(
|
||||||
|
new ZoneWave(desertWastes, 60),
|
||||||
|
new Unlock(Blocks.daggerFactory),
|
||||||
|
new Unlock(Blocks.draugFactory),
|
||||||
|
new Unlock(Blocks.door),
|
||||||
|
new Unlock(Blocks.waterExtractor)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 1)
|
frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 1)
|
||||||
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))){{
|
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))){{
|
||||||
loadout = Loadouts.basicFoundation;
|
loadout = Loadouts.basicFoundation;
|
||||||
baseLaunchCost = ItemStack.with();
|
startingItems = list(copper, 250);
|
||||||
startingItems = ItemStack.list(Items.copper, 250);
|
|
||||||
conditionWave = 10;
|
conditionWave = 10;
|
||||||
blockRequirements = new Block[]{Blocks.junction, Blocks.router};
|
resources = with(copper, lead, coal);
|
||||||
zoneRequirements = ZoneRequirement.with(groundZero, 10);
|
requirements = with(
|
||||||
resources = new Item[]{Items.copper, Items.lead, Items.coal};
|
new ZoneWave(groundZero, 10),
|
||||||
|
new Unlock(Blocks.junction),
|
||||||
|
new Unlock(Blocks.router)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
craters = new Zone("craters", new MapGenerator("craters", 1).decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.004))){{
|
craters = new Zone("craters", new MapGenerator("craters", 1).decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.004))){{
|
||||||
startingItems = ItemStack.list(Items.copper, 100);
|
startingItems = list(copper, 100);
|
||||||
conditionWave = 10;
|
conditionWave = 10;
|
||||||
zoneRequirements = ZoneRequirement.with(frozenForest, 10);
|
resources = with(copper, lead, coal, sand, scrap);
|
||||||
blockRequirements = new Block[]{Blocks.mender, Blocks.combustionGenerator};
|
requirements = with(
|
||||||
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.sand, Items.scrap};
|
new ZoneWave(frozenForest, 10),
|
||||||
|
new Unlock(Blocks.mender),
|
||||||
|
new Unlock(Blocks.combustionGenerator)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1)){{
|
ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1)){{
|
||||||
loadout = Loadouts.basicFoundation;
|
loadout = Loadouts.basicFoundation;
|
||||||
baseLaunchCost = ItemStack.with();
|
startingItems = list(copper, 140, lead, 50);
|
||||||
startingItems = ItemStack.list(Items.copper, 140, Items.lead, 50);
|
|
||||||
conditionWave = 20;
|
conditionWave = 20;
|
||||||
launchPeriod = 20;
|
launchPeriod = 20;
|
||||||
zoneRequirements = ZoneRequirement.with(desertWastes, 20, craters, 15);
|
resources = with(copper, scrap, lead, coal, sand);
|
||||||
blockRequirements = new Block[]{Blocks.graphitePress, Blocks.combustionGenerator, Blocks.kiln, Blocks.mechanicalPump};
|
requirements = with(
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand};
|
new ZoneWave(desertWastes, 20),
|
||||||
|
new ZoneWave(craters, 15),
|
||||||
|
new Unlock(Blocks.graphitePress),
|
||||||
|
new Unlock(Blocks.combustionGenerator),
|
||||||
|
new Unlock(Blocks.kiln),
|
||||||
|
new Unlock(Blocks.mechanicalPump)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2)
|
stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2)
|
||||||
.decor(new Decoration(Blocks.shale, Blocks.shaleBoulder, 0.02))){{
|
.decor(new Decoration(Blocks.shale, Blocks.shaleBoulder, 0.02))){{
|
||||||
loadout = Loadouts.basicFoundation;
|
loadout = Loadouts.basicFoundation;
|
||||||
startingItems = ItemStack.list(Items.copper, 200, Items.lead, 50);
|
startingItems = list(copper, 200, lead, 50);
|
||||||
conditionWave = 10;
|
conditionWave = 10;
|
||||||
launchPeriod = 10;
|
launchPeriod = 10;
|
||||||
zoneRequirements = ZoneRequirement.with(frozenForest, 15);
|
resources = with(copper, scrap, lead, coal, titanium, sand);
|
||||||
blockRequirements = new Block[]{Blocks.pneumaticDrill, Blocks.powerNode, Blocks.turbineGenerator};
|
requirements = with(
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand};
|
new ZoneWave(frozenForest, 15),
|
||||||
|
new Unlock(Blocks.pneumaticDrill),
|
||||||
|
new Unlock(Blocks.powerNode),
|
||||||
|
new Unlock(Blocks.turbineGenerator)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
fungalPass = new Zone("fungalPass", new MapGenerator("fungalPass")){{
|
fungalPass = new Zone("fungalPass", new MapGenerator("fungalPass")){{
|
||||||
startingItems = ItemStack.list(Items.copper, 250, Items.lead, 250, Items.metaglass, 100, Items.graphite, 100);
|
startingItems = list(copper, 250, lead, 250, Items.metaglass, 100, Items.graphite, 100);
|
||||||
zoneRequirements = ZoneRequirement.with(stainedMountains, 15);
|
resources = with(copper, lead, coal, titanium, sand);
|
||||||
blockRequirements = new Block[]{Blocks.daggerFactory, Blocks.crawlerFactory, Blocks.door, Blocks.siliconSmelter};
|
configureObjective = new Launched(this);
|
||||||
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.titanium, Items.sand};
|
requirements = with(
|
||||||
|
new ZoneWave(stainedMountains, 15),
|
||||||
|
new Unlock(Blocks.daggerFactory),
|
||||||
|
new Unlock(Blocks.crawlerFactory),
|
||||||
|
new Unlock(Blocks.door),
|
||||||
|
new Unlock(Blocks.siliconSmelter)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
overgrowth = new Zone("overgrowth", new MapGenerator("overgrowth")){{
|
overgrowth = new Zone("overgrowth", new MapGenerator("overgrowth")){{
|
||||||
startingItems = ItemStack.list(Items.copper, 1500, Items.lead, 1000, Items.silicon, 500, Items.metaglass, 250);
|
startingItems = list(copper, 1500, lead, 1000, Items.silicon, 500, Items.metaglass, 250);
|
||||||
conditionWave = 12;
|
conditionWave = 12;
|
||||||
launchPeriod = 4;
|
launchPeriod = 4;
|
||||||
loadout = Loadouts.basicNucleus;
|
loadout = Loadouts.basicNucleus;
|
||||||
zoneRequirements = ZoneRequirement.with(craters, 40, fungalPass, 10);
|
configureObjective = new Launched(this);
|
||||||
blockRequirements = new Block[]{Blocks.cultivator, Blocks.sporePress, Blocks.titanFactory, Blocks.wraithFactory};
|
resources = with(copper, lead, coal, titanium, sand, thorium, scrap);
|
||||||
resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.titanium, Items.sand, Items.thorium, Items.scrap};
|
requirements = with(
|
||||||
|
new ZoneWave(craters, 40),
|
||||||
|
new Launched(fungalPass),
|
||||||
|
new Unlock(Blocks.cultivator),
|
||||||
|
new Unlock(Blocks.sporePress),
|
||||||
|
new Unlock(Blocks.titanFactory),
|
||||||
|
new Unlock(Blocks.wraithFactory)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
tarFields = new Zone("tarFields", new MapGenerator("tarFields")
|
tarFields = new Zone("tarFields", new MapGenerator("tarFields")
|
||||||
.decor(new Decoration(Blocks.shale, Blocks.shaleBoulder, 0.02))){{
|
.decor(new Decoration(Blocks.shale, Blocks.shaleBoulder, 0.02))){{
|
||||||
loadout = Loadouts.basicFoundation;
|
loadout = Loadouts.basicFoundation;
|
||||||
startingItems = ItemStack.list(Items.copper, 250, Items.lead, 100);
|
startingItems = list(copper, 250, lead, 100);
|
||||||
conditionWave = 15;
|
conditionWave = 15;
|
||||||
launchPeriod = 10;
|
launchPeriod = 10;
|
||||||
zoneRequirements = ZoneRequirement.with(ruinousShores, 20);
|
requirements = with(new ZoneWave(ruinousShores, 20));
|
||||||
blockRequirements = new Block[]{Blocks.coalCentrifuge, Blocks.conduit, Blocks.wave};
|
resources = with(copper, scrap, lead, coal, titanium, thorium, sand);
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium, Items.sand};
|
requirements = with(
|
||||||
|
new ZoneWave(ruinousShores, 20),
|
||||||
|
new Unlock(Blocks.coalCentrifuge),
|
||||||
|
new Unlock(Blocks.conduit),
|
||||||
|
new Unlock(Blocks.wave)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift")){{
|
desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift")){{
|
||||||
loadout = Loadouts.basicNucleus;
|
loadout = Loadouts.basicNucleus;
|
||||||
baseLaunchCost = ItemStack.with();
|
startingItems = list(copper, 1000, lead, 1000, Items.graphite, 250, titanium, 250, Items.silicon, 250);
|
||||||
startingItems = ItemStack.list(Items.copper, 1000, Items.lead, 1000, Items.graphite, 250, Items.titanium, 250, Items.silicon, 250);
|
|
||||||
conditionWave = 3;
|
conditionWave = 3;
|
||||||
launchPeriod = 2;
|
launchPeriod = 2;
|
||||||
zoneRequirements = ZoneRequirement.with(tarFields, 20);
|
resources = with(copper, scrap, lead, coal, titanium, sand, thorium);
|
||||||
blockRequirements = new Block[]{Blocks.thermalGenerator, Blocks.thoriumReactor};
|
requirements = with(
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand, Items.thorium};
|
new ZoneWave(tarFields, 20),
|
||||||
|
new Unlock(Blocks.thermalGenerator),
|
||||||
|
new Unlock(Blocks.thoriumReactor)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -174,21 +218,23 @@ public class Zones implements ContentList{
|
|||||||
startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 2000, Items.graphite, 500, Items.titanium, 500, Items.silicon, 500);
|
startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 2000, Items.graphite, 500, Items.titanium, 500, Items.silicon, 500);
|
||||||
conditionWave = 3;
|
conditionWave = 3;
|
||||||
launchPeriod = 2;
|
launchPeriod = 2;
|
||||||
zoneRequirements = ZoneRequirement.with(stainedMountains, 40);
|
requirements = with(stainedMountains, 40);
|
||||||
blockRequirements = new Block[]{Blocks.thermalGenerator};
|
blockRequirements = new Block[]{Blocks.thermalGenerator};
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand};
|
resources = Array.with(Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand};
|
||||||
}};*/
|
}};*/
|
||||||
|
|
||||||
nuclearComplex = new Zone("nuclearComplex", new MapGenerator("nuclearProductionComplex", 1)
|
nuclearComplex = new Zone("nuclearComplex", new MapGenerator("nuclearProductionComplex", 1)
|
||||||
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{
|
.decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{
|
||||||
loadout = Loadouts.basicNucleus;
|
loadout = Loadouts.basicNucleus;
|
||||||
baseLaunchCost = ItemStack.with();
|
startingItems = list(copper, 1250, lead, 1500, Items.silicon, 400, Items.metaglass, 250);
|
||||||
startingItems = ItemStack.list(Items.copper, 1250, Items.lead, 1500, Items.silicon, 400, Items.metaglass, 250);
|
|
||||||
conditionWave = 30;
|
conditionWave = 30;
|
||||||
launchPeriod = 15;
|
launchPeriod = 15;
|
||||||
zoneRequirements = ZoneRequirement.with(fungalPass, 8);
|
resources = with(copper, scrap, lead, coal, titanium, thorium, sand);
|
||||||
blockRequirements = new Block[]{Blocks.thermalGenerator, Blocks.laserDrill};
|
requirements = with(
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium, Items.sand};
|
new Launched(fungalPass),
|
||||||
|
new Unlock(Blocks.thermalGenerator),
|
||||||
|
new Unlock(Blocks.laserDrill)
|
||||||
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -198,9 +244,9 @@ public class Zones implements ContentList{
|
|||||||
startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 2000, Items.graphite, 500, Items.titanium, 500, Items.silicon, 500);
|
startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 2000, Items.graphite, 500, Items.titanium, 500, Items.silicon, 500);
|
||||||
conditionWave = 3;
|
conditionWave = 3;
|
||||||
launchPeriod = 2;
|
launchPeriod = 2;
|
||||||
zoneRequirements = ZoneRequirement.with(nuclearComplex, 40);
|
requirements = with(nuclearComplex, 40);
|
||||||
blockRequirements = new Block[]{Blocks.thermalGenerator};
|
blockRequirements = new Block[]{Blocks.thermalGenerator};
|
||||||
resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium};
|
resources = Array.with(Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium};
|
||||||
}};*/
|
}};*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package io.anuke.mindustry.core;
|
|||||||
|
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.assets.*;
|
import io.anuke.arc.assets.*;
|
||||||
|
import io.anuke.arc.audio.*;
|
||||||
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.input.*;
|
import io.anuke.arc.input.*;
|
||||||
@@ -54,6 +56,9 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
Events.on(StateChangeEvent.class, event -> {
|
Events.on(StateChangeEvent.class, event -> {
|
||||||
if((event.from == State.playing && event.to == State.menu) || (event.from == State.menu && event.to != State.menu)){
|
if((event.from == State.playing && event.to == State.menu) || (event.from == State.menu && event.to != State.menu)){
|
||||||
Time.runTask(5f, platform::updateRPC);
|
Time.runTask(5f, platform::updateRPC);
|
||||||
|
for(Sound sound : assets.getAll(Sound.class, new Array<>())){
|
||||||
|
sound.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -146,11 +151,15 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
});
|
});
|
||||||
|
|
||||||
Events.on(ZoneRequireCompleteEvent.class, e -> {
|
Events.on(ZoneRequireCompleteEvent.class, e -> {
|
||||||
ui.hudfrag.showToast(Core.bundle.format("zone.requirement.complete", state.wave, e.zone.localizedName));
|
if(e.objective.display() != null){
|
||||||
|
ui.hudfrag.showToast(Core.bundle.format("zone.requirement.complete", e.zoneForMet.localizedName, e.objective.display()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(ZoneConfigureCompleteEvent.class, e -> {
|
Events.on(ZoneConfigureCompleteEvent.class, e -> {
|
||||||
ui.hudfrag.showToast(Core.bundle.format("zone.config.complete", e.zone.configureWave));
|
if(e.zone.configureObjective.display() != null){
|
||||||
|
ui.hudfrag.showToast(Core.bundle.format("zone.config.unlocked", e.zone.configureObjective.display()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(Trigger.newGame, () -> {
|
Events.on(Trigger.newGame, () -> {
|
||||||
@@ -166,6 +175,12 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
Effects.shake(5f, 5f, core);
|
Effects.shake(5f, 5f, core);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Events.on(UnitDestroyEvent.class, e -> {
|
||||||
|
if(e.unit instanceof BaseUnit && world.isZone()){
|
||||||
|
data.unlockContent(((BaseUnit)e.unit).getType());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -401,6 +416,7 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
|
|
||||||
music.update();
|
music.update();
|
||||||
loops.update();
|
loops.update();
|
||||||
|
Time.updateGlobal();
|
||||||
|
|
||||||
if(Core.input.keyTap(Binding.fullscreen)){
|
if(Core.input.keyTap(Binding.fullscreen)){
|
||||||
boolean full = settings.getBool("fullscreen");
|
boolean full = settings.getBool("fullscreen");
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package io.anuke.mindustry.core;
|
|||||||
|
|
||||||
import io.anuke.annotations.Annotations.*;
|
import io.anuke.annotations.Annotations.*;
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.ObjectSet.*;
|
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.core.GameState.*;
|
import io.anuke.mindustry.core.GameState.*;
|
||||||
@@ -136,8 +135,7 @@ public class Logic implements ApplicationListener{
|
|||||||
public void runWave(){
|
public void runWave(){
|
||||||
spawner.spawnEnemies();
|
spawner.spawnEnemies();
|
||||||
state.wave++;
|
state.wave++;
|
||||||
state.wavetime = world.isZone() && world.getZone().isBossWave(state.wave) ? state.rules.waveSpacing * state.rules.bossWaveMultiplier :
|
state.wavetime = world.isZone() && world.getZone().isLaunchWave(state.wave) ? state.rules.waveSpacing * state.rules.launchWaveMultiplier : state.rules.waveSpacing;
|
||||||
world.isZone() && world.getZone().isLaunchWave(state.wave) ? state.rules.waveSpacing * state.rules.launchWaveMultiplier : state.rules.waveSpacing;
|
|
||||||
|
|
||||||
Events.fire(new WaveEvent());
|
Events.fire(new WaveEvent());
|
||||||
}
|
}
|
||||||
@@ -176,12 +174,16 @@ public class Logic implements ApplicationListener{
|
|||||||
ui.hudfrag.showLaunch();
|
ui.hudfrag.showLaunch();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){
|
for(Tile tile : state.teams.get(defaultTeam).cores){
|
||||||
Effects.effect(Fx.launch, tile);
|
Effects.effect(Fx.launch, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(world.getZone() != null){
|
||||||
|
world.getZone().setLaunched();
|
||||||
|
}
|
||||||
|
|
||||||
Time.runTask(30f, () -> {
|
Time.runTask(30f, () -> {
|
||||||
for(Tile tile : new ObjectSetIterator<>(state.teams.get(defaultTeam).cores)){
|
for(Tile tile : state.teams.get(defaultTeam).cores){
|
||||||
for(Item item : content.items()){
|
for(Item item : content.items()){
|
||||||
if(tile == null || tile.entity == null || tile.entity.items == null) continue;
|
if(tile == null || tile.entity == null || tile.entity.items == null) continue;
|
||||||
data.addItem(item, tile.entity.items.get(item));
|
data.addItem(item, tile.entity.items.get(item));
|
||||||
|
|||||||
@@ -94,11 +94,6 @@ public class NetServer implements ApplicationListener{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(admins.isIDBanned(uuid)){
|
|
||||||
con.kick(KickReason.banned);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(admins.getPlayerLimit() > 0 && playerGroup.size() >= admins.getPlayerLimit()){
|
if(admins.getPlayerLimit() > 0 && playerGroup.size() >= admins.getPlayerLimit()){
|
||||||
con.kick(KickReason.playerLimit);
|
con.kick(KickReason.playerLimit);
|
||||||
return;
|
return;
|
||||||
@@ -357,6 +352,11 @@ public class NetServer implements ApplicationListener{
|
|||||||
if(currentlyKicking[0] == null){
|
if(currentlyKicking[0] == null){
|
||||||
player.sendMessage("[scarlet]Nobody is being voted on.");
|
player.sendMessage("[scarlet]Nobody is being voted on.");
|
||||||
}else{
|
}else{
|
||||||
|
if(player.isLocal){
|
||||||
|
player.sendMessage("Local players can't vote. Kick the player yourself instead.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//hosts can vote all they want
|
//hosts can vote all they want
|
||||||
if(player.uuid != null && (currentlyKicking[0].voted.contains(player.uuid) || currentlyKicking[0].voted.contains(admins.getInfo(player.uuid).lastIP))){
|
if(player.uuid != null && (currentlyKicking[0].voted.contains(player.uuid) || currentlyKicking[0].voted.contains(admins.getInfo(player.uuid).lastIP))){
|
||||||
player.sendMessage("[scarlet]You've already voted. Sit down.");
|
player.sendMessage("[scarlet]You've already voted. Sit down.");
|
||||||
|
|||||||
@@ -31,11 +31,16 @@ public interface Platform{
|
|||||||
return Array.with();
|
return Array.with();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Steam: Return external workshop mods to be loaded.*/
|
||||||
|
default Array<FileHandle> getExternalMods(){
|
||||||
|
return Array.with();
|
||||||
|
}
|
||||||
|
|
||||||
/** Steam: View a map listing on the workshop.*/
|
/** Steam: View a map listing on the workshop.*/
|
||||||
default void viewMapListing(Map map){}
|
default void viewMapListing(Map map){}
|
||||||
|
|
||||||
/** Steam: View a map listing on the workshop.*/
|
/** Steam: View a listing on the workshop.*/
|
||||||
default void viewMapListing(String mapid){}
|
default void viewListing(String mapid){}
|
||||||
|
|
||||||
/** Steam: View map workshop info, removing the map ID tag if its listing is deleted.
|
/** Steam: View map workshop info, removing the map ID tag if its listing is deleted.
|
||||||
* Also presents the option to update the map. */
|
* Also presents the option to update the map. */
|
||||||
|
|||||||
@@ -238,7 +238,6 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
Core.scene.add(menuGroup);
|
Core.scene.add(menuGroup);
|
||||||
Core.scene.add(hudGroup);
|
Core.scene.add(hudGroup);
|
||||||
|
|
||||||
control.input.getFrag().build(hudGroup);
|
|
||||||
hudfrag.build(hudGroup);
|
hudfrag.build(hudGroup);
|
||||||
menufrag.build(menuGroup);
|
menufrag.build(menuGroup);
|
||||||
chatfrag.container().build(hudGroup);
|
chatfrag.container().build(hudGroup);
|
||||||
@@ -284,7 +283,7 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
new Dialog(titleText){{
|
new Dialog(titleText){{
|
||||||
cont.margin(30).add(dtext).padRight(6f);
|
cont.margin(30).add(dtext).padRight(6f);
|
||||||
TextFieldFilter filter = inumeric ? TextFieldFilter.digitsOnly : (f, c) -> true;
|
TextFieldFilter filter = inumeric ? TextFieldFilter.digitsOnly : (f, c) -> true;
|
||||||
TextField field = cont.addField(def, t -> {}).size(170f, 50f).get();
|
TextField field = cont.addField(def, t -> {}).size(330f, 50f).get();
|
||||||
field.setFilter((f, c) -> field.getText().length() < textLength && filter.acceptChar(f, c));
|
field.setFilter((f, c) -> field.getText().length() < textLength && filter.acceptChar(f, c));
|
||||||
buttons.defaults().size(120, 54).pad(4);
|
buttons.defaults().size(120, 54).pad(4);
|
||||||
buttons.addButton("$ok", () -> {
|
buttons.addButton("$ok", () -> {
|
||||||
|
|||||||
@@ -272,6 +272,7 @@ public class World{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeBlock(Tile tile){
|
public void removeBlock(Tile tile){
|
||||||
|
if(tile == null) return;
|
||||||
tile.link().getLinkedTiles(other -> other.setBlock(Blocks.air));
|
tile.link().getLinkedTiles(other -> other.setBlock(Blocks.air));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
menu.cont.addImageTextButton("$editor.publish.workshop", Icon.linkSmall, () -> {
|
menu.cont.addImageTextButton("$editor.publish.workshop", Icon.linkSmall, () -> {
|
||||||
Map builtin = maps.all().find(m -> m.name().equals(editor.getTags().get("name", "").trim()));
|
Map builtin = maps.all().find(m -> m.name().equals(editor.getTags().get("name", "").trim()));
|
||||||
if(editor.getTags().containsKey("steamid") && builtin != null && !builtin.custom){
|
if(editor.getTags().containsKey("steamid") && builtin != null && !builtin.custom){
|
||||||
platform.viewMapListing(editor.getTags().get("steamid"));
|
platform.viewListing(editor.getTags().get("steamid"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ public class ArtilleryBulletType extends BasicBulletType{
|
|||||||
hitSound = Sounds.explosion;
|
hitSound = Sounds.explosion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArtilleryBulletType(){
|
||||||
|
this(1f, 1f, "shell");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(io.anuke.mindustry.entities.type.Bullet b){
|
public void update(io.anuke.mindustry.entities.type.Bullet b){
|
||||||
super.update(b);
|
super.update(b);
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ public class BasicBulletType extends BulletType{
|
|||||||
this.bulletSprite = bulletSprite;
|
this.bulletSprite = bulletSprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** For mods. */
|
||||||
|
public BasicBulletType(){
|
||||||
|
this(1f, 1f, "bullet");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
backRegion = Core.atlas.find(bulletSprite + "-back");
|
backRegion = Core.atlas.find(bulletSprite + "-back");
|
||||||
|
|||||||
@@ -17,4 +17,8 @@ public class BombBulletType extends BasicBulletType{
|
|||||||
collidesAir = false;
|
collidesAir = false;
|
||||||
hitSound = Sounds.explosion;
|
hitSound = Sounds.explosion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BombBulletType(){
|
||||||
|
this(1f, 1f, "shell");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ public abstract class FlakBulletType extends BasicBulletType{
|
|||||||
bulletHeight = 10f;
|
bulletHeight = 10f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FlakBulletType(){
|
||||||
|
this(1f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Bullet b){
|
public void update(Bullet b){
|
||||||
super.update(b);
|
super.update(b);
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ public class HealBulletType extends BulletType{
|
|||||||
collidesTeam = true;
|
collidesTeam = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HealBulletType(){
|
||||||
|
this(1f, 1f);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean collides(Bullet b, Tile tile){
|
public boolean collides(Bullet b, Tile tile){
|
||||||
return tile.getTeam() != b.getTeam() || tile.entity.healthf() < 1f;
|
return tile.getTeam() != b.getTeam() || tile.entity.healthf() < 1f;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package io.anuke.mindustry.entities.bullet;
|
|||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.math.geom.*;
|
import io.anuke.arc.math.geom.*;
|
||||||
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.entities.*;
|
import io.anuke.mindustry.entities.*;
|
||||||
import io.anuke.mindustry.entities.effect.*;
|
import io.anuke.mindustry.entities.effect.*;
|
||||||
@@ -13,14 +14,17 @@ import io.anuke.mindustry.world.*;
|
|||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class LiquidBulletType extends BulletType{
|
public class LiquidBulletType extends BulletType{
|
||||||
Liquid liquid;
|
@NonNull Liquid liquid;
|
||||||
|
|
||||||
public LiquidBulletType(Liquid liquid){
|
public LiquidBulletType(@Nullable Liquid liquid){
|
||||||
super(3.5f, 0);
|
super(3.5f, 0);
|
||||||
|
|
||||||
|
if(liquid != null){
|
||||||
this.liquid = liquid;
|
this.liquid = liquid;
|
||||||
|
this.status = liquid.effect;
|
||||||
|
}
|
||||||
|
|
||||||
lifetime = 74f;
|
lifetime = 74f;
|
||||||
status = liquid.effect;
|
|
||||||
statusDuration = 90f;
|
statusDuration = 90f;
|
||||||
despawnEffect = Fx.none;
|
despawnEffect = Fx.none;
|
||||||
hitEffect = Fx.hitLiquid;
|
hitEffect = Fx.hitLiquid;
|
||||||
@@ -30,13 +34,17 @@ public class LiquidBulletType extends BulletType{
|
|||||||
knockback = 0.55f;
|
knockback = 0.55f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiquidBulletType(){
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float range(){
|
public float range(){
|
||||||
return speed * lifetime / 2f;
|
return speed * lifetime / 2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(io.anuke.mindustry.entities.type.Bullet b){
|
public void update(Bullet b){
|
||||||
super.update(b);
|
super.update(b);
|
||||||
|
|
||||||
if(liquid.canExtinguish()){
|
if(liquid.canExtinguish()){
|
||||||
@@ -50,7 +58,7 @@ public class LiquidBulletType extends BulletType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(io.anuke.mindustry.entities.type.Bullet b){
|
public void draw(Bullet b){
|
||||||
Draw.color(liquid.color, Color.white, b.fout() / 100f);
|
Draw.color(liquid.color, Color.white, b.fout() / 100f);
|
||||||
|
|
||||||
Fill.circle(b.x, b.y, 0.5f + b.fout() * 2.5f);
|
Fill.circle(b.x, b.y, 0.5f + b.fout() * 2.5f);
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ public class MissileBulletType extends BasicBulletType{
|
|||||||
hitSound = Sounds.explosion;
|
hitSound = Sounds.explosion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MissileBulletType(){
|
||||||
|
this(1f, 1f, "missile");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Bullet b){
|
public void update(Bullet b){
|
||||||
super.update(b);
|
super.update(b);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import io.anuke.arc.collection.*;
|
|||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.math.geom.*;
|
import io.anuke.arc.math.geom.*;
|
||||||
import io.anuke.arc.util.*;
|
|
||||||
import io.anuke.arc.util.ArcAnnotate.*;
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.*;
|
import io.anuke.mindustry.*;
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.entities.type.*;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
@@ -188,6 +188,11 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
|||||||
|
|
||||||
/** Add another build requests to the tail of the queue, if it doesn't exist there yet. */
|
/** Add another build requests to the tail of the queue, if it doesn't exist there yet. */
|
||||||
default void addBuildRequest(BuildRequest place){
|
default void addBuildRequest(BuildRequest place){
|
||||||
|
addBuildRequest(place, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add another build requests to the queue, if it doesn't exist there yet. */
|
||||||
|
default void addBuildRequest(BuildRequest place, boolean tail){
|
||||||
for(BuildRequest request : buildQueue()){
|
for(BuildRequest request : buildQueue()){
|
||||||
if(request.x == place.x && request.y == place.y){
|
if(request.x == place.x && request.y == place.y){
|
||||||
return;
|
return;
|
||||||
@@ -197,7 +202,11 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
|||||||
if(tile != null && tile.entity instanceof BuildEntity){
|
if(tile != null && tile.entity instanceof BuildEntity){
|
||||||
place.progress = tile.<BuildEntity>entity().progress;
|
place.progress = tile.<BuildEntity>entity().progress;
|
||||||
}
|
}
|
||||||
|
if(tail){
|
||||||
buildQueue().addLast(place);
|
buildQueue().addLast(place);
|
||||||
|
}else{
|
||||||
|
buildQueue().addFirst(place);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -258,15 +267,19 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
|||||||
|
|
||||||
/** Class for storing build requests. Can be either a place or remove request. */
|
/** Class for storing build requests. Can be either a place or remove request. */
|
||||||
class BuildRequest{
|
class BuildRequest{
|
||||||
public final int x, y, rotation;
|
public int x, y, rotation;
|
||||||
public final Block block;
|
public @Nullable Block block;
|
||||||
public final boolean breaking;
|
public boolean breaking;
|
||||||
public boolean hasConfig;
|
public boolean hasConfig;
|
||||||
public int config;
|
public int config;
|
||||||
|
|
||||||
public float progress;
|
public float progress;
|
||||||
public boolean initialized;
|
public boolean initialized;
|
||||||
|
|
||||||
|
//animation variables
|
||||||
|
public float animScale = 0f;
|
||||||
|
public float animInvalid;
|
||||||
|
|
||||||
/** This creates a build request. */
|
/** This creates a build request. */
|
||||||
public BuildRequest(int x, int y, int rotation, Block block){
|
public BuildRequest(int x, int y, int rotation, Block block){
|
||||||
this.x = x;
|
this.x = x;
|
||||||
@@ -285,13 +298,42 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
|||||||
this.breaking = true;
|
this.breaking = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BuildRequest(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle bounds(Rectangle rect){
|
||||||
|
if(breaking){
|
||||||
|
return rect.set(-100f, -100f, 0f, 0f);
|
||||||
|
}else{
|
||||||
|
return block.bounds(x, y, rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildRequest set(int x, int y, int rotation, Block block){
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.rotation = rotation;
|
||||||
|
this.block = block;
|
||||||
|
this.breaking = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float drawx(){
|
||||||
|
return x*tilesize + block.offset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float drawy(){
|
||||||
|
return y*tilesize + block.offset();
|
||||||
|
}
|
||||||
|
|
||||||
public BuildRequest configure(int config){
|
public BuildRequest configure(int config){
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.hasConfig = true;
|
this.hasConfig = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile tile(){
|
public @Nullable Tile tile(){
|
||||||
return world.tile(x, y);
|
return world.tile(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ import io.anuke.mindustry.entities.*;
|
|||||||
import io.anuke.mindustry.entities.traits.*;
|
import io.anuke.mindustry.entities.traits.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
|
||||||
import io.anuke.mindustry.input.*;
|
import io.anuke.mindustry.input.*;
|
||||||
import io.anuke.mindustry.input.InputHandler.*;
|
|
||||||
import io.anuke.mindustry.io.*;
|
import io.anuke.mindustry.io.*;
|
||||||
import io.anuke.mindustry.net.Administration.*;
|
import io.anuke.mindustry.net.Administration.*;
|
||||||
import io.anuke.mindustry.net.*;
|
import io.anuke.mindustry.net.*;
|
||||||
@@ -51,7 +49,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
public String name = "noname";
|
public String name = "noname";
|
||||||
public @Nullable
|
public @Nullable
|
||||||
String uuid, usid;
|
String uuid, usid;
|
||||||
public boolean isAdmin, isTransferring, isShooting, isBoosting, isMobile, isTyping;
|
public boolean isAdmin, isTransferring, isShooting, isBoosting, isMobile, isTyping, isBuilding = true;
|
||||||
public float boostHeat, shootHeat, destructTime;
|
public float boostHeat, shootHeat, destructTime;
|
||||||
public boolean achievedFlight;
|
public boolean achievedFlight;
|
||||||
public Color color = new Color();
|
public Color color = new Color();
|
||||||
@@ -357,7 +355,13 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
public void drawOver(){
|
public void drawOver(){
|
||||||
if(dead) return;
|
if(dead) return;
|
||||||
|
|
||||||
drawMechanics();
|
if(isBuilding()){
|
||||||
|
if(!state.isPaused() && isBuilding){
|
||||||
|
drawBuilding();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
drawMining();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -424,57 +428,17 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
|
|
||||||
/** Draw all current build requests. Does not draw the beam effect, only the positions. */
|
/** Draw all current build requests. Does not draw the beam effect, only the positions. */
|
||||||
public void drawBuildRequests(){
|
public void drawBuildRequests(){
|
||||||
BuildRequest last = null;
|
if(!isLocal) return;
|
||||||
|
|
||||||
for(BuildRequest request : buildQueue()){
|
for(BuildRequest request : buildQueue()){
|
||||||
if(request.progress > 0.01f || (buildRequest() == request && request.initialized && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue;
|
if(request.progress > 0.01f || (buildRequest() == request && request.initialized && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue;
|
||||||
|
|
||||||
|
request.animScale = 1f;
|
||||||
if(request.breaking){
|
if(request.breaking){
|
||||||
Block block = world.ltile(request.x, request.y).block();
|
control.input.drawBreaking(request);
|
||||||
|
|
||||||
//draw removal request
|
|
||||||
Lines.stroke(2f, Pal.removeBack);
|
|
||||||
|
|
||||||
float rad = Mathf.absin(Time.time(), 7f, 1f) + block.size * tilesize / 2f - 1;
|
|
||||||
Lines.square(
|
|
||||||
request.x * tilesize + block.offset(),
|
|
||||||
request.y * tilesize + block.offset() - 1,
|
|
||||||
rad);
|
|
||||||
|
|
||||||
Draw.color(Pal.remove);
|
|
||||||
|
|
||||||
Lines.square(
|
|
||||||
request.x * tilesize + block.offset(),
|
|
||||||
request.y * tilesize + block.offset(), rad);
|
|
||||||
}else{
|
}else{
|
||||||
Draw.color();
|
request.block.drawRequest(request, control.input.allRequests(),
|
||||||
PlaceDraw draw = PlaceDraw.instance;
|
Build.validPlace(getTeam(), request.x, request.y, request.block, request.rotation));
|
||||||
|
|
||||||
draw.scalex = 1;
|
|
||||||
draw.scaley = 1;
|
|
||||||
draw.rotation = request.rotation;
|
|
||||||
|
|
||||||
if(last == null){
|
|
||||||
request.block.getPlaceDraw(draw, request.rotation, request.x, request.y, request.rotation);
|
|
||||||
}else{
|
|
||||||
request.block.getPlaceDraw(draw, request.rotation, last.x - request.x, last.y - request.y, last.rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureRegion region = draw.region;
|
|
||||||
|
|
||||||
Draw.rect(region,
|
|
||||||
request.x * tilesize + request.block.offset(), request.y * tilesize + request.block.offset(),
|
|
||||||
region.getWidth() * 1f * Draw.scl * draw.scalex,
|
|
||||||
region.getHeight() * 1f * Draw.scl * draw.scaley, request.block.rotate ? draw.rotation * 90 : 0);
|
|
||||||
|
|
||||||
Draw.color(Pal.accent);
|
|
||||||
for(int i = 0; i < 4; i++){
|
|
||||||
Point2 p = Geometry.d8edge[i];
|
|
||||||
float offset = -Math.max(request.block.size - 1, 0) / 2f * tilesize;
|
|
||||||
Draw.rect("block-select", request.x * tilesize + request.block.offset() + offset * p.x, request.y * tilesize + request.block.offset() + offset * p.y, i * 90);
|
|
||||||
}
|
|
||||||
Draw.color();
|
|
||||||
|
|
||||||
last = request;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,6 +449,18 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
|
|
||||||
//region update methods
|
//region update methods
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateMechanics(){
|
||||||
|
if(isBuilding){
|
||||||
|
updateBuilding();
|
||||||
|
}
|
||||||
|
|
||||||
|
//mine only when not building
|
||||||
|
if(buildRequest() == null){
|
||||||
|
updateMining();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
hitTime -= Time.delta();
|
hitTime -= Time.delta();
|
||||||
@@ -517,7 +493,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
BuildRequest request = buildRequest();
|
BuildRequest request = buildRequest();
|
||||||
if(isBuilding() && request.tile() != null && (request.tile().withinDst(x, y, placeDistance) || state.isEditor())){
|
if(isBuilding() && isBuilding && request.tile() != null && (request.tile().withinDst(x, y, placeDistance) || state.isEditor())){
|
||||||
loops.play(Sounds.build, request.tile(), 0.75f);
|
loops.play(Sounds.build, request.tile(), 0.75f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -817,6 +793,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
placeQueue.clear();
|
placeQueue.clear();
|
||||||
dead = true;
|
dead = true;
|
||||||
lastText = null;
|
lastText = null;
|
||||||
|
isBuilding = true;
|
||||||
textFadeTime = 0f;
|
textFadeTime = 0f;
|
||||||
target = null;
|
target = null;
|
||||||
moveTarget = null;
|
moveTarget = null;
|
||||||
@@ -910,7 +887,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
public void write(DataOutput buffer) throws IOException{
|
public void write(DataOutput buffer) throws IOException{
|
||||||
super.writeSave(buffer, !isLocal);
|
super.writeSave(buffer, !isLocal);
|
||||||
TypeIO.writeStringData(buffer, name);
|
TypeIO.writeStringData(buffer, name);
|
||||||
buffer.writeByte(Pack.byteValue(isAdmin) | (Pack.byteValue(dead) << 1) | (Pack.byteValue(isBoosting) << 2) | (Pack.byteValue(isTyping) << 3));
|
buffer.writeByte(Pack.byteValue(isAdmin) | (Pack.byteValue(dead) << 1) | (Pack.byteValue(isBoosting) << 2) | (Pack.byteValue(isTyping) << 3)| (Pack.byteValue(isBuilding) << 4));
|
||||||
buffer.writeInt(Color.rgba8888(color));
|
buffer.writeInt(Color.rgba8888(color));
|
||||||
buffer.writeByte(mech.id);
|
buffer.writeByte(mech.id);
|
||||||
buffer.writeInt(mining == null ? noSpawner : mining.pos());
|
buffer.writeInt(mining == null ? noSpawner : mining.pos());
|
||||||
@@ -932,6 +909,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
dead = (bools & 2) != 0;
|
dead = (bools & 2) != 0;
|
||||||
boolean boosting = (bools & 4) != 0;
|
boolean boosting = (bools & 4) != 0;
|
||||||
isTyping = (bools & 8) != 0;
|
isTyping = (bools & 8) != 0;
|
||||||
|
boolean building = (bools & 16) != 0;
|
||||||
color.set(buffer.readInt());
|
color.set(buffer.readInt());
|
||||||
mech = content.getByID(ContentType.mech, buffer.readByte());
|
mech = content.getByID(ContentType.mech, buffer.readByte());
|
||||||
int mine = buffer.readInt();
|
int mine = buffer.readInt();
|
||||||
@@ -950,6 +928,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
velocity.y = lastvy;
|
velocity.y = lastvy;
|
||||||
}else{
|
}else{
|
||||||
mining = world.tile(mine);
|
mining = world.tile(mine);
|
||||||
|
isBuilding = building;
|
||||||
isBoosting = boosting;
|
isBoosting = boosting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
package io.anuke.mindustry.game;
|
package io.anuke.mindustry.game;
|
||||||
|
|
||||||
|
import io.anuke.arc.files.*;
|
||||||
import io.anuke.arc.util.ArcAnnotate.*;
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.*;
|
||||||
import io.anuke.mindustry.mod.Mods.*;
|
import io.anuke.mindustry.mod.Mods.*;
|
||||||
import io.anuke.mindustry.type.ContentType;
|
import io.anuke.mindustry.type.*;
|
||||||
|
|
||||||
|
|
||||||
/** Base class for a content type that is loaded in {@link io.anuke.mindustry.core.ContentLoader}. */
|
/** Base class for a content type that is loaded in {@link io.anuke.mindustry.core.ContentLoader}. */
|
||||||
public abstract class Content{
|
public abstract class Content implements Comparable<Content>{
|
||||||
public final short id;
|
public final short id;
|
||||||
/** The mod that loaded this piece of content. */
|
/** The mod that loaded this piece of content. */
|
||||||
public @Nullable LoadedMod mod;
|
public @Nullable LoadedMod mod;
|
||||||
|
/** File that this content was loaded from. */
|
||||||
|
public @Nullable FileHandle sourceFile;
|
||||||
|
|
||||||
public Content(){
|
public Content(){
|
||||||
this.id = (short)Vars.content.getBy(getContentType()).size;
|
this.id = (short)Vars.content.getBy(getContentType()).size;
|
||||||
@@ -34,6 +37,11 @@ public abstract class Content{
|
|||||||
public void load(){
|
public void load(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Content c){
|
||||||
|
return Integer.compare(id, c.id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return getContentType().name() + "#" + id;
|
return getContentType().name() + "#" + id;
|
||||||
|
|||||||
@@ -61,11 +61,13 @@ public class EventType{
|
|||||||
|
|
||||||
/** Called when a zone's requirements are met. */
|
/** Called when a zone's requirements are met. */
|
||||||
public static class ZoneRequireCompleteEvent{
|
public static class ZoneRequireCompleteEvent{
|
||||||
public final Zone zone, required;
|
public final Zone zoneMet, zoneForMet;
|
||||||
|
public final Objective objective;
|
||||||
|
|
||||||
public ZoneRequireCompleteEvent(Zone zone, Zone required){
|
public ZoneRequireCompleteEvent(Zone zoneMet, Zone zoneForMet, Objective objective){
|
||||||
this.zone = zone;
|
this.zoneMet = zoneMet;
|
||||||
this.required = required;
|
this.zoneForMet = zoneForMet;
|
||||||
|
this.objective = objective;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +132,13 @@ public class EventType{
|
|||||||
|
|
||||||
/** Called when a player deposits items to a block.*/
|
/** Called when a player deposits items to a block.*/
|
||||||
public static class DepositEvent{
|
public static class DepositEvent{
|
||||||
|
public final Tile tile;
|
||||||
|
public final Player player;
|
||||||
|
|
||||||
|
public DepositEvent(Tile tile, Player player){
|
||||||
|
this.tile = tile;
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GameOverEvent{
|
public static class GameOverEvent{
|
||||||
|
|||||||
@@ -91,12 +91,17 @@ public class GlobalData{
|
|||||||
state.stats.itemsDelivered.getAndIncrement(item, 0, amount);
|
state.stats.itemsDelivered.getAndIncrement(item, 0, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasItems(Array<ItemStack> stacks){
|
||||||
|
return !stacks.contains(s -> items.get(s.item, 0) < s.amount);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasItems(ItemStack[] stacks){
|
public boolean hasItems(ItemStack[] stacks){
|
||||||
for(ItemStack stack : stacks){
|
for(ItemStack stack : stacks){
|
||||||
if(items.get(stack.item, 0) < stack.amount){
|
if(!has(stack.item, stack.amount)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +112,13 @@ public class GlobalData{
|
|||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeItems(Array<ItemStack> stacks){
|
||||||
|
for(ItemStack stack : stacks){
|
||||||
|
items.getAndIncrement(stack.item, 0, -stack.amount);
|
||||||
|
}
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean has(Item item, int amount){
|
public boolean has(Item item, int amount){
|
||||||
return items.get(item, 0) >= amount;
|
return items.get(item, 0) >= amount;
|
||||||
}
|
}
|
||||||
|
|||||||
27
core/src/io/anuke/mindustry/game/Objective.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package io.anuke.mindustry.game;
|
||||||
|
|
||||||
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
|
import io.anuke.mindustry.game.Objectives.*;
|
||||||
|
import io.anuke.mindustry.type.*;
|
||||||
|
|
||||||
|
/** Defines a specific objective for a game. */
|
||||||
|
public interface Objective{
|
||||||
|
|
||||||
|
/** @return whether this objective is met. */
|
||||||
|
boolean complete();
|
||||||
|
|
||||||
|
/** @return the string displayed when this objective is completed, in imperative form.
|
||||||
|
* e.g. when the objective is 'complete 10 waves', this would display "complete 10 waves".
|
||||||
|
* If this objective should not be displayed, should return null.*/
|
||||||
|
@Nullable String display();
|
||||||
|
|
||||||
|
/** Build a display for this zone requirement.*/
|
||||||
|
default void build(Table table){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
default Zone zone(){
|
||||||
|
return this instanceof ZoneObjective ? ((ZoneObjective)this).zone : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
96
core/src/io/anuke/mindustry/game/Objectives.java
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package io.anuke.mindustry.game;
|
||||||
|
|
||||||
|
import io.anuke.arc.*;
|
||||||
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
|
import io.anuke.mindustry.type.*;
|
||||||
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
|
/** Holds objective classes. */
|
||||||
|
public class Objectives{
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
public static class Wave implements Objective{
|
||||||
|
public int wave;
|
||||||
|
|
||||||
|
public Wave(int wave){
|
||||||
|
this.wave = wave;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Wave(){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean complete(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String display(){
|
||||||
|
//TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Unlock implements Objective{
|
||||||
|
public @NonNull Block block;
|
||||||
|
|
||||||
|
public Unlock(Block block){
|
||||||
|
this.block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Unlock(){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean complete(){
|
||||||
|
return block.unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String display(){
|
||||||
|
return Core.bundle.format("requirement.unlock", block.localizedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ZoneWave extends ZoneObjective{
|
||||||
|
public int wave;
|
||||||
|
|
||||||
|
public ZoneWave(Zone zone, int wave){
|
||||||
|
this.zone = zone;
|
||||||
|
this.wave = wave;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ZoneWave(){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean complete(){
|
||||||
|
return zone.bestWave() >= wave;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String display(){
|
||||||
|
return Core.bundle.format("requirement.wave", wave, zone.localizedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Launched extends ZoneObjective{
|
||||||
|
|
||||||
|
public Launched(Zone zone){
|
||||||
|
this.zone = zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Launched(){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean complete(){
|
||||||
|
return zone.hasLaunched();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String display(){
|
||||||
|
return Core.bundle.format("requirement.core", zone.localizedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class ZoneObjective implements Objective{
|
||||||
|
public @NonNull Zone zone;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package io.anuke.mindustry.game;
|
package io.anuke.mindustry.game;
|
||||||
|
|
||||||
import io.anuke.annotations.Annotations.Serialize;
|
import io.anuke.annotations.Annotations.*;
|
||||||
import io.anuke.arc.collection.Array;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.mindustry.content.Items;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.io.JsonIO;
|
import io.anuke.mindustry.io.*;
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.type.Zone;
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines current rules on how the game should function.
|
* Defines current rules on how the game should function.
|
||||||
@@ -69,6 +69,8 @@ public class Rules{
|
|||||||
public boolean tutorial = false;
|
public boolean tutorial = false;
|
||||||
/** Starting items put in cores */
|
/** Starting items put in cores */
|
||||||
public Array<ItemStack> loadout = Array.with(ItemStack.with(Items.copper, 100));
|
public Array<ItemStack> loadout = Array.with(ItemStack.with(Items.copper, 100));
|
||||||
|
/** Blocks that cannot be placed. */
|
||||||
|
public ObjectSet<Block> bannedBlocks = new ObjectSet<>();
|
||||||
|
|
||||||
/** Copies this ruleset exactly. Not very efficient at all, do not use often. */
|
/** Copies this ruleset exactly. Not very efficient at all, do not use often. */
|
||||||
public Rules copy(){
|
public Rules copy(){
|
||||||
|
|||||||
@@ -31,7 +31,11 @@ public abstract class UnlockableContent extends MappableContent{
|
|||||||
/** Returns a specific content icon, or the region {contentType}-{name} if not found.*/
|
/** Returns a specific content icon, or the region {contentType}-{name} if not found.*/
|
||||||
public TextureRegion icon(Cicon icon){
|
public TextureRegion icon(Cicon icon){
|
||||||
if(cicons[icon.ordinal()] == null){
|
if(cicons[icon.ordinal()] == null){
|
||||||
cicons[icon.ordinal()] = Core.atlas.find(getContentType().name() + "-" + name + "-" + icon.name(), Core.atlas.find(getContentType().name() + "-" + name + "-full", Core.atlas.find(getContentType().name() + "-" + name, Core.atlas.find(name))));
|
cicons[icon.ordinal()] = Core.atlas.find(getContentType().name() + "-" + name + "-" + icon.name(),
|
||||||
|
Core.atlas.find(getContentType().name() + "-" + name + "-full",
|
||||||
|
Core.atlas.find(getContentType().name() + "-" + name,
|
||||||
|
Core.atlas.find(name,
|
||||||
|
Core.atlas.find(name + "1")))));
|
||||||
}
|
}
|
||||||
return cicons[icon.ordinal()];
|
return cicons[icon.ordinal()];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ import io.anuke.arc.math.*;
|
|||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.entities.type.base.*;
|
import io.anuke.mindustry.entities.type.base.*;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.game.Teams.*;
|
import io.anuke.mindustry.game.Teams.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
import io.anuke.mindustry.world.Block.*;
|
|
||||||
|
|
||||||
import static io.anuke.arc.Core.camera;
|
import static io.anuke.arc.Core.camera;
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
@@ -131,7 +130,7 @@ public class BlockRenderer implements Disposable{
|
|||||||
if(!camera.bounds(Tmp.r1).grow(tilesize * 2f).overlaps(Tmp.r2.setSize(b.size * tilesize).setCenter(block.x * tilesize + b.offset(), block.y * tilesize + b.offset()))) continue;
|
if(!camera.bounds(Tmp.r1).grow(tilesize * 2f).overlaps(Tmp.r2.setSize(b.size * tilesize).setCenter(block.x * tilesize + b.offset(), block.y * tilesize + b.offset()))) continue;
|
||||||
|
|
||||||
Draw.alpha(0.5f);
|
Draw.alpha(0.5f);
|
||||||
Draw.mixcol(Pal.accent, 0.2f + Mathf.absin(5f, 0.2f));
|
Draw.mixcol(Color.white, 0.2f + Mathf.absin(Time.globalTime(), 6f, 0.2f));
|
||||||
Draw.rect(b.icon(Cicon.full), block.x * tilesize + b.offset(), block.y * tilesize + b.offset(), b.rotate ? block.rotation * 90 : 0f);
|
Draw.rect(b.icon(Cicon.full), block.x * tilesize + b.offset(), block.y * tilesize + b.offset(), b.rotate ? block.rotation * 90 : 0f);
|
||||||
}
|
}
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
@@ -242,28 +241,34 @@ public class BlockRenderer implements Disposable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawBlocks(Layer stopAt){
|
public void drawBlocks(Layer stopAt){
|
||||||
|
int startIdx = iterateidx;
|
||||||
for(; iterateidx < requestidx; iterateidx++){
|
for(; iterateidx < requestidx; iterateidx++){
|
||||||
|
BlockRequest request = requests.get(iterateidx);
|
||||||
|
|
||||||
if(iterateidx < requests.size && requests.get(iterateidx).layer.ordinal() > stopAt.ordinal()){
|
if(request.layer.ordinal() > stopAt.ordinal()){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockRequest req = requests.get(iterateidx);
|
if(request.layer == Layer.power){
|
||||||
Block block = req.tile.block();
|
if(iterateidx - startIdx > 0 && request.tile.pos() == requests.get(iterateidx - 1).tile.pos()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(req.layer == Layer.block){
|
Block block = request.tile.block();
|
||||||
block.draw(req.tile);
|
|
||||||
if(req.tile.entity != null && req.tile.entity.damaged()){
|
if(request.layer == Layer.block){
|
||||||
block.drawCracks(req.tile);
|
block.draw(request.tile);
|
||||||
|
if(request.tile.entity != null && request.tile.entity.damaged()){
|
||||||
|
block.drawCracks(request.tile);
|
||||||
}
|
}
|
||||||
if(block.synthetic() && req.tile.getTeam() != player.getTeam()){
|
if(block.synthetic() && request.tile.getTeam() != player.getTeam()){
|
||||||
block.drawTeam(req.tile);
|
block.drawTeam(request.tile);
|
||||||
}
|
}
|
||||||
}else if(req.layer == block.layer){
|
}else if(request.layer == block.layer){
|
||||||
block.drawLayer(req.tile);
|
block.drawLayer(request.tile);
|
||||||
}else if(req.layer == block.layer2){
|
}else if(request.layer == block.layer2){
|
||||||
block.drawLayer2(req.tile);
|
block.drawLayer2(request.tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,7 +333,9 @@ public class BlockRenderer implements Disposable{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(BlockRequest other){
|
public int compareTo(BlockRequest other){
|
||||||
return layer.compareTo(other.layer);
|
int compare = layer.compareTo(other.layer);
|
||||||
|
|
||||||
|
return (compare != 0) ? compare : Integer.compare(tile.pos(), other.tile.pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ public class OverlayRenderer{
|
|||||||
public void drawBottom(){
|
public void drawBottom(){
|
||||||
InputHandler input = control.input;
|
InputHandler input = control.input;
|
||||||
|
|
||||||
if(!input.isDrawing() || player.isDead()) return;
|
if(player.isDead()) return;
|
||||||
|
|
||||||
input.drawOutlined();
|
input.drawBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawTop(){
|
public void drawTop(){
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ public enum Binding implements KeyBind{
|
|||||||
select(KeyCode.MOUSE_LEFT),
|
select(KeyCode.MOUSE_LEFT),
|
||||||
deselect(KeyCode.MOUSE_RIGHT),
|
deselect(KeyCode.MOUSE_RIGHT),
|
||||||
break_block(KeyCode.MOUSE_RIGHT),
|
break_block(KeyCode.MOUSE_RIGHT),
|
||||||
|
clear_building(KeyCode.Q),
|
||||||
|
pause_building(KeyCode.E),
|
||||||
rotate(new Axis(KeyCode.SCROLL)),
|
rotate(new Axis(KeyCode.SCROLL)),
|
||||||
rotateplaced(KeyCode.R),
|
rotateplaced(KeyCode.R),
|
||||||
diagonal_placement(KeyCode.CONTROL_LEFT),
|
diagonal_placement(KeyCode.CONTROL_LEFT),
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import io.anuke.arc.Graphics.*;
|
|||||||
import io.anuke.arc.Graphics.Cursor.*;
|
import io.anuke.arc.Graphics.Cursor.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.math.geom.*;
|
import io.anuke.arc.scene.*;
|
||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
import io.anuke.mindustry.content.*;
|
|
||||||
import io.anuke.mindustry.core.GameState.*;
|
import io.anuke.mindustry.core.GameState.*;
|
||||||
|
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.input.PlaceUtils.*;
|
import io.anuke.mindustry.ui.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
import static io.anuke.arc.Core.scene;
|
import static io.anuke.arc.Core.scene;
|
||||||
@@ -23,101 +23,77 @@ import static io.anuke.mindustry.input.PlaceMode.*;
|
|||||||
public class DesktopInput extends InputHandler{
|
public class DesktopInput extends InputHandler{
|
||||||
/** Current cursor type. */
|
/** Current cursor type. */
|
||||||
private Cursor cursorType = SystemCursor.arrow;
|
private Cursor cursorType = SystemCursor.arrow;
|
||||||
|
|
||||||
/** Position where the player started dragging a line. */
|
/** Position where the player started dragging a line. */
|
||||||
private int selectX, selectY;
|
private int selectX, selectY;
|
||||||
|
/** Last known line positions.*/
|
||||||
|
private int lastLineX, lastLineY;
|
||||||
/** Whether selecting mode is active. */
|
/** Whether selecting mode is active. */
|
||||||
private PlaceMode mode;
|
private PlaceMode mode;
|
||||||
/** Animation scale for line. */
|
/** Animation scale for line. */
|
||||||
private float selectScale;
|
private float selectScale;
|
||||||
|
/** Selected build request for movement. */
|
||||||
|
private @Nullable BuildRequest sreq;
|
||||||
|
/** Whether player is currently deleting removal requests. */
|
||||||
|
private boolean deleting = false;
|
||||||
|
|
||||||
private int prevX, prevY, prevRotation;
|
@Override
|
||||||
|
public void buildUI(Group group){
|
||||||
/** Draws a placement icon for a specific block. */
|
group.fill(t -> {
|
||||||
void drawPlace(int x, int y, Block block, int rotation, int prevX, int prevY, int prevRotation){
|
t.bottom().update(() -> t.getColor().a = Mathf.lerpDelta(t.getColor().a, player.isBuilding() ? 1f : 0f, 0.15f));
|
||||||
if(validPlace(x, y, block, rotation)){
|
t.visible(() -> Core.settings.getBool("hints"));
|
||||||
block.getPlaceDraw(placeDraw, rotation, prevX, prevY, prevRotation);
|
t.table(Styles.black6, b -> {
|
||||||
|
b.defaults().left();
|
||||||
Draw.color();
|
b.label(() -> Core.bundle.format(!player.isBuilding ? "resumebuilding" : "pausebuilding", Core.keybinds.get(Binding.pause_building).key.name())).style(Styles.outlineLabel);
|
||||||
Draw.mixcol(Pal.accent, 0.12f + Mathf.absin(Time.time(), 8f, 0.35f));
|
b.row();
|
||||||
Draw.rect(placeDraw.region, x * tilesize + block.offset(), y * tilesize + block.offset(),
|
b.add(Core.bundle.format("cancelbuilding", Core.keybinds.get(Binding.clear_building).key.name())).style(Styles.outlineLabel);
|
||||||
placeDraw.region.getWidth() * selectScale * Draw.scl * placeDraw.scalex,
|
}).margin(10f);
|
||||||
placeDraw.region.getHeight() * selectScale * Draw.scl * placeDraw.scaley,
|
});
|
||||||
block.rotate ? placeDraw.rotation * 90 : 0);
|
|
||||||
|
|
||||||
Draw.color(Pal.accent);
|
|
||||||
for(int i = 0; i < 4; i++){
|
|
||||||
Point2 p = Geometry.d8edge[i];
|
|
||||||
float offset = -Math.max(block.size - 1, 0) / 2f * tilesize;
|
|
||||||
if(i % 2 == 0)
|
|
||||||
Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y, i * 90);
|
|
||||||
}
|
|
||||||
Draw.color();
|
|
||||||
Draw.mixcol();
|
|
||||||
}else{
|
|
||||||
Draw.color(Pal.removeBack);
|
|
||||||
Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset() - 1, block.size * tilesize / 2f - 1);
|
|
||||||
Draw.color(Pal.remove);
|
|
||||||
Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset(), block.size * tilesize / 2f - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDrawing(){
|
public void drawTop(){
|
||||||
return mode != none || block != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void drawOutlined(){
|
|
||||||
Lines.stroke(1f);
|
Lines.stroke(1f);
|
||||||
int cursorX = tileX(Core.input.mouseX());
|
int cursorX = tileX(Core.input.mouseX());
|
||||||
int cursorY = tileY(Core.input.mouseY());
|
int cursorY = tileY(Core.input.mouseY());
|
||||||
|
|
||||||
//draw selection(s)
|
//draw selection(s)
|
||||||
if(mode == placing && block != null){
|
if(mode == placing && block != null){
|
||||||
prevX = selectX;
|
for(int i = 0; i < lineRequests.size; i++){
|
||||||
prevY = selectY;
|
BuildRequest req = lineRequests.get(i);
|
||||||
prevRotation = rotation;
|
if(i == lineRequests.size - 1 && req.block.rotate){
|
||||||
|
drawArrow(block, req.x, req.y, req.rotation);
|
||||||
iterateLine(selectX, selectY, cursorX, cursorY, l -> {
|
}
|
||||||
if(l.last && block.rotate){
|
drawRequest(lineRequests.get(i));
|
||||||
drawArrow(block, l.x, l.y, l.rotation);
|
|
||||||
}
|
}
|
||||||
drawPlace(l.x, l.y, block, l.rotation, prevX - l.x, prevY - l.y, prevRotation);
|
|
||||||
|
|
||||||
prevX = l.x;
|
|
||||||
prevY = l.y;
|
|
||||||
prevRotation = l.rotation;
|
|
||||||
});
|
|
||||||
|
|
||||||
}else if(mode == breaking){
|
}else if(mode == breaking){
|
||||||
NormalizeDrawResult result = PlaceUtils.normalizeDrawArea(Blocks.air, selectX, selectY, cursorX, cursorY, false, maxLength, 1f);
|
drawSelection(selectX, selectY, cursorX, cursorY);
|
||||||
NormalizeResult dresult = PlaceUtils.normalizeArea(selectX, selectY, cursorX, cursorY, rotation, false, maxLength);
|
|
||||||
|
|
||||||
for(int x = dresult.x; x <= dresult.x2; x++){
|
|
||||||
for(int y = dresult.y; y <= dresult.y2; y++){
|
|
||||||
Tile tile = world.ltile(x, y);
|
|
||||||
if(tile == null || !validBreak(tile.x, tile.y)) continue;
|
|
||||||
|
|
||||||
Draw.color(Pal.removeBack);
|
|
||||||
Lines.square(tile.drawx(), tile.drawy() - 1, tile.block().size * tilesize / 2f - 1);
|
|
||||||
Draw.color(Pal.remove);
|
|
||||||
Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Draw.color(Pal.removeBack);
|
|
||||||
Lines.rect(result.x, result.y - 1, result.x2 - result.x, result.y2 - result.y);
|
|
||||||
Draw.color(Pal.remove);
|
|
||||||
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
|
||||||
}else if(isPlacing()){
|
}else if(isPlacing()){
|
||||||
if(block.rotate){
|
if(block.rotate){
|
||||||
drawArrow(block, cursorX, cursorY, rotation);
|
drawArrow(block, cursorX, cursorY, rotation);
|
||||||
}
|
}
|
||||||
drawPlace(cursorX, cursorY, block, rotation, cursorX, cursorY, rotation);
|
Draw.color();
|
||||||
|
drawRequest(cursorX, cursorY, block, rotation);
|
||||||
block.drawPlace(cursorX, cursorY, rotation, validPlace(cursorX, cursorY, block, rotation));
|
block.drawPlace(cursorX, cursorY, rotation, validPlace(cursorX, cursorY, block, rotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mode == none && !isPlacing()){
|
||||||
|
BuildRequest req = getRequest(cursorX, cursorY);
|
||||||
|
if(req != null){
|
||||||
|
drawSelected(req.x, req.y, req.breaking ? req.tile().block() : req.block, Pal.accent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sreq != null){
|
||||||
|
boolean valid = validPlace(sreq.x, sreq.y, sreq.block, sreq.rotation, sreq);
|
||||||
|
if(sreq.block.rotate){
|
||||||
|
drawArrow(sreq.block, sreq.x, sreq.y, sreq.rotation, valid);
|
||||||
|
}
|
||||||
|
|
||||||
|
sreq.block.drawRequest(sreq, allRequests(), valid);
|
||||||
|
|
||||||
|
drawSelected(sreq.x, sreq.y, sreq.block, getRequest(sreq.x, sreq.y, sreq.block.size, sreq) != null ? Pal.remove : Pal.accent);
|
||||||
|
}
|
||||||
|
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,6 +147,14 @@ public class DesktopInput extends InputHandler{
|
|||||||
|
|
||||||
rotation = Mathf.mod(rotation + (int)Core.input.axisTap(Binding.rotate), 4);
|
rotation = Mathf.mod(rotation + (int)Core.input.axisTap(Binding.rotate), 4);
|
||||||
|
|
||||||
|
if(sreq != null){
|
||||||
|
sreq.rotation = Mathf.mod(sreq.rotation + (int)Core.input.axisTap(Binding.rotate), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Math.abs((int)Core.input.axisTap(Binding.rotate)) > 0 && isPlacing() && mode == placing){
|
||||||
|
updateLine(selectX, selectY);
|
||||||
|
}
|
||||||
|
|
||||||
Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY());
|
Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY());
|
||||||
|
|
||||||
if(cursor != null){
|
if(cursor != null){
|
||||||
@@ -186,6 +170,10 @@ public class DesktopInput extends InputHandler{
|
|||||||
cursorType = ui.drillCursor;
|
cursorType = ui.drillCursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(getRequest(cursor.x, cursor.y) != null && mode == none){
|
||||||
|
cursorType = SystemCursor.hand;
|
||||||
|
}
|
||||||
|
|
||||||
if(canTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y)){
|
if(canTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y)){
|
||||||
cursorType = ui.unloadCursor;
|
cursorType = ui.unloadCursor;
|
||||||
}
|
}
|
||||||
@@ -211,11 +199,46 @@ public class DesktopInput extends InputHandler{
|
|||||||
player.setMineTile(null);
|
player.setMineTile(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Core.input.keyTap(Binding.clear_building)){
|
||||||
|
player.clearBuilding();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sreq != null){
|
||||||
|
float offset = ((sreq.block.size + 2) % 2) * tilesize / 2f;
|
||||||
|
float x = Core.input.mouseWorld().x + offset;
|
||||||
|
float y = Core.input.mouseWorld().y + offset;
|
||||||
|
sreq.x = (int)(x / tilesize);
|
||||||
|
sreq.y = (int)(y / tilesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(block == null || mode != placing){
|
||||||
|
lineRequests.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Core.input.keyTap(Binding.pause_building)){
|
||||||
|
player.isBuilding = !player.isBuilding;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((cursorX != lastLineX || cursorY != lastLineY) && isPlacing() && mode == placing){
|
||||||
|
updateLine(selectX, selectY);
|
||||||
|
lastLineX = cursorX;
|
||||||
|
lastLineY = cursorY;
|
||||||
|
}
|
||||||
|
|
||||||
if(Core.input.keyTap(Binding.select) && !Core.scene.hasMouse()){
|
if(Core.input.keyTap(Binding.select) && !Core.scene.hasMouse()){
|
||||||
|
BuildRequest req = getRequest(cursorX, cursorY);
|
||||||
|
|
||||||
if(isPlacing()){
|
if(isPlacing()){
|
||||||
selectX = cursorX;
|
selectX = cursorX;
|
||||||
selectY = cursorY;
|
selectY = cursorY;
|
||||||
|
lastLineX = cursorX;
|
||||||
|
lastLineY = cursorY;
|
||||||
mode = placing;
|
mode = placing;
|
||||||
|
updateLine(selectX, selectY);
|
||||||
|
}else if(req != null && !req.breaking && mode == none && !req.initialized){
|
||||||
|
sreq = req;
|
||||||
|
}else if(req != null && req.breaking){
|
||||||
|
deleting = true;
|
||||||
}else if(selected != null){
|
}else if(selected != null){
|
||||||
//only begin shooting if there's no cursor event
|
//only begin shooting if there's no cursor event
|
||||||
if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.buildQueue().size == 0 && !droppingItem &&
|
if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.buildQueue().size == 0 && !droppingItem &&
|
||||||
@@ -225,21 +248,26 @@ public class DesktopInput extends InputHandler{
|
|||||||
}else if(!ui.chatfrag.chatOpen()){ //if it's out of bounds, shooting is just fine
|
}else if(!ui.chatfrag.chatOpen()){ //if it's out of bounds, shooting is just fine
|
||||||
player.isShooting = true;
|
player.isShooting = true;
|
||||||
}
|
}
|
||||||
}else if(Core.input.keyTap(Binding.deselect) && (block != null || mode != none || player.isBuilding()) &&
|
}else if(Core.input.keyTap(Binding.deselect) && block != null){
|
||||||
!(player.buildRequest() != null && player.buildRequest().breaking && Core.keybinds.get(Binding.deselect) == Core.keybinds.get(Binding.break_block))){
|
|
||||||
if(block == null){
|
|
||||||
player.clearBuilding();
|
|
||||||
}
|
|
||||||
|
|
||||||
block = null;
|
block = null;
|
||||||
mode = none;
|
mode = none;
|
||||||
}else if(Core.input.keyTap(Binding.break_block) && !Core.scene.hasMouse()){
|
}else if(Core.input.keyTap(Binding.break_block) && !Core.scene.hasMouse()){
|
||||||
//is recalculated because setting the mode to breaking removes potential multiblock cursor offset
|
//is recalculated because setting the mode to breaking removes potential multiblock cursor offset
|
||||||
|
deleting = false;
|
||||||
mode = breaking;
|
mode = breaking;
|
||||||
selectX = tileX(Core.input.mouseX());
|
selectX = tileX(Core.input.mouseX());
|
||||||
selectY = tileY(Core.input.mouseY());
|
selectY = tileY(Core.input.mouseY());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Core.input.keyDown(Binding.select) && mode == none && !isPlacing() && deleting){
|
||||||
|
BuildRequest req = getRequest(cursorX, cursorY);
|
||||||
|
if(req != null && req.breaking){
|
||||||
|
player.buildQueue().remove(req);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
deleting = false;
|
||||||
|
}
|
||||||
|
|
||||||
if(mode == placing && block != null){
|
if(mode == placing && block != null){
|
||||||
if(!overrideLineRotation && !Core.input.keyDown(Binding.diagonal_placement) && (selectX != cursorX || selectY != cursorY) && ((int) Core.input.axisTap(Binding.rotate) != 0)){
|
if(!overrideLineRotation && !Core.input.keyDown(Binding.diagonal_placement) && (selectX != cursorX || selectY != cursorY) && ((int) Core.input.axisTap(Binding.rotate) != 0)){
|
||||||
rotation = ((int)((Angles.angle(selectX, selectY, cursorX, cursorY) + 45) / 90f)) % 4;
|
rotation = ((int)((Angles.angle(selectX, selectY, cursorX, cursorY) + 45) / 90f)) % 4;
|
||||||
@@ -252,27 +280,24 @@ public class DesktopInput extends InputHandler{
|
|||||||
if(Core.input.keyRelease(Binding.break_block) || Core.input.keyRelease(Binding.select)){
|
if(Core.input.keyRelease(Binding.break_block) || Core.input.keyRelease(Binding.select)){
|
||||||
|
|
||||||
if(mode == placing && block != null){ //touch up while placing, place everything in selection
|
if(mode == placing && block != null){ //touch up while placing, place everything in selection
|
||||||
iterateLine(selectX, selectY, cursorX, cursorY, l -> {
|
flushRequests(lineRequests);
|
||||||
rotation = l.rotation;
|
lineRequests.clear();
|
||||||
tryPlaceBlock(l.x, l.y);
|
|
||||||
});
|
|
||||||
Events.fire(new LineConfirmEvent());
|
Events.fire(new LineConfirmEvent());
|
||||||
}else if(mode == breaking){ //touch up while breaking, break everything in selection
|
}else if(mode == breaking){ //touch up while breaking, break everything in selection
|
||||||
NormalizeResult result = PlaceUtils.normalizeArea(selectX, selectY, cursorX, cursorY, rotation, false, maxLength);
|
removeSelection(selectX, selectY, cursorX, cursorY);
|
||||||
for(int x = 0; x <= Math.abs(result.x2 - result.x); x++){
|
|
||||||
for(int y = 0; y <= Math.abs(result.y2 - result.y); y++){
|
|
||||||
int wx = selectX + x * Mathf.sign(cursorX - selectX);
|
|
||||||
int wy = selectY + y * Mathf.sign(cursorY - selectY);
|
|
||||||
|
|
||||||
tryBreakBlock(wx, wy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selected != null){
|
if(selected != null){
|
||||||
tryDropItems(selected.link(), Core.input.mouseWorld().x, Core.input.mouseWorld().y);
|
tryDropItems(selected.link(), Core.input.mouseWorld().x, Core.input.mouseWorld().y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(sreq != null){
|
||||||
|
if(getRequest(sreq.x, sreq.y, sreq.block.size, sreq) != null){
|
||||||
|
player.buildQueue().remove(sreq, true);
|
||||||
|
}
|
||||||
|
sreq = null;
|
||||||
|
}
|
||||||
|
|
||||||
mode = none;
|
mode = none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,6 +323,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
droppingItem = false;
|
droppingItem = false;
|
||||||
mode = none;
|
mode = none;
|
||||||
block = null;
|
block = null;
|
||||||
|
sreq = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ import io.anuke.arc.function.*;
|
|||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.input.*;
|
import io.anuke.arc.input.*;
|
||||||
|
import io.anuke.arc.input.GestureDetector.*;
|
||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.math.geom.*;
|
import io.anuke.arc.math.geom.*;
|
||||||
|
import io.anuke.arc.scene.*;
|
||||||
|
import io.anuke.arc.scene.event.*;
|
||||||
import io.anuke.arc.scene.ui.layout.*;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
@@ -17,21 +20,26 @@ import io.anuke.mindustry.entities.effect.*;
|
|||||||
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||||
import io.anuke.mindustry.entities.type.*;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
|
import io.anuke.mindustry.game.Teams.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
|
import io.anuke.mindustry.input.PlaceUtils.*;
|
||||||
import io.anuke.mindustry.net.*;
|
import io.anuke.mindustry.net.*;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.ui.fragments.*;
|
import io.anuke.mindustry.ui.fragments.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public abstract class InputHandler implements InputProcessor{
|
public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||||
/** Used for dropping items. */
|
/** Used for dropping items. */
|
||||||
final static float playerSelectRange = mobile ? 17f : 11f;
|
final static float playerSelectRange = mobile ? 17f : 11f;
|
||||||
/** Maximum line length. */
|
/** Maximum line length. */
|
||||||
final static int maxLength = 100;
|
final static int maxLength = 100;
|
||||||
final static Vector2 stackTrns = new Vector2();
|
final static Vector2 stackTrns = new Vector2();
|
||||||
|
final static Rectangle r1 = new Rectangle(), r2 = new Rectangle();
|
||||||
/** Distance on the back from where items originate. */
|
/** Distance on the back from where items originate. */
|
||||||
final static float backTrns = 3f;
|
final static float backTrns = 3f;
|
||||||
|
|
||||||
@@ -41,9 +49,14 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
public boolean overrideLineRotation;
|
public boolean overrideLineRotation;
|
||||||
public int rotation;
|
public int rotation;
|
||||||
public boolean droppingItem;
|
public boolean droppingItem;
|
||||||
|
public Group uiGroup;
|
||||||
|
|
||||||
protected PlaceDraw placeDraw = new PlaceDraw();
|
protected GestureDetector detector;
|
||||||
private PlaceLine line = new PlaceLine();
|
protected PlaceLine line = new PlaceLine();
|
||||||
|
protected BuildRequest resultreq;
|
||||||
|
protected BuildRequest brequest = new BuildRequest();
|
||||||
|
protected Array<BuildRequest> lineRequests = new Array<>();
|
||||||
|
protected Array<BuildRequest> selectRequests = new Array<>();
|
||||||
|
|
||||||
//methods to override
|
//methods to override
|
||||||
|
|
||||||
@@ -92,7 +105,7 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
int[] remaining = {accepted, accepted};
|
int[] remaining = {accepted, accepted};
|
||||||
Block block = tile.block();
|
Block block = tile.block();
|
||||||
|
|
||||||
Events.fire(new DepositEvent());
|
Core.app.post(() -> Events.fire(new DepositEvent(tile, player)));
|
||||||
|
|
||||||
for(int i = 0; i < sent; i++){
|
for(int i = 0; i < sent; i++){
|
||||||
boolean end = i == sent - 1;
|
boolean end = i == sent - 1;
|
||||||
@@ -134,6 +147,14 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
tile.block().configured(tile, player, value);
|
tile.block().configured(tile, player, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Eachable<BuildRequest> allRequests(){
|
||||||
|
return cons -> {
|
||||||
|
for(BuildRequest request : player.buildQueue()) cons.accept(request);
|
||||||
|
for(BuildRequest request : selectRequests) cons.accept(request);
|
||||||
|
for(BuildRequest request : lineRequests) cons.accept(request);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public OverlayFragment getFrag(){
|
public OverlayFragment getFrag(){
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
@@ -150,7 +171,11 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
return Core.input.mouseY();
|
return Core.input.mouseY();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildUI(Table table){
|
public void buildPlacementUI(Table table){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildUI(Group group){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +183,7 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawOutlined(){
|
public void drawBottom(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,8 +191,217 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDrawing(){
|
public void drawSelected(int x, int y, Block block, Color color){
|
||||||
return false;
|
Draw.color(color);
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
Point2 p = Geometry.d8edge[i];
|
||||||
|
float offset = -Math.max(block.size - 1, 0) / 2f * tilesize;
|
||||||
|
Draw.rect("block-select",
|
||||||
|
x*tilesize + block.offset() + offset * p.x,
|
||||||
|
y*tilesize + block.offset() + offset * p.y, i * 90);
|
||||||
|
}
|
||||||
|
Draw.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawBreaking(BuildRequest request){
|
||||||
|
if(request.breaking){
|
||||||
|
drawBreaking(request.x, request.y);
|
||||||
|
}else{
|
||||||
|
drawSelected(request.x, request.y, request.tile().block(), Pal.remove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawBreaking(int x, int y){
|
||||||
|
Tile tile = world.ltile(x, y);
|
||||||
|
if(tile == null) return;
|
||||||
|
Block block = tile.block();
|
||||||
|
|
||||||
|
drawSelected(x, y, block, Pal.remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the selection request that overlaps this position, or null. */
|
||||||
|
protected BuildRequest getRequest(int x, int y){
|
||||||
|
return getRequest(x, y, 1, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the selection request that overlaps this position, or null. */
|
||||||
|
protected BuildRequest getRequest(int x, int y, int size, BuildRequest skip){
|
||||||
|
float offset = ((size + 1) % 2) * tilesize / 2f;
|
||||||
|
r2.setSize(tilesize * size);
|
||||||
|
r2.setCenter(x * tilesize + offset, y * tilesize + offset);
|
||||||
|
resultreq = null;
|
||||||
|
|
||||||
|
Predicate<BuildRequest> test = req -> {
|
||||||
|
if(req == skip) return false;
|
||||||
|
Tile other = req.tile();
|
||||||
|
|
||||||
|
if(other == null) return false;
|
||||||
|
|
||||||
|
if(!req.breaking){
|
||||||
|
r1.setSize(req.block.size * tilesize);
|
||||||
|
r1.setCenter(other.worldx() + req.block.offset(), other.worldy() + req.block.offset());
|
||||||
|
}else{
|
||||||
|
r1.setSize(other.block().size * tilesize);
|
||||||
|
r1.setCenter(other.worldx() + other.block().offset(), other.worldy() + other.block().offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
return r2.overlaps(r1);
|
||||||
|
};
|
||||||
|
|
||||||
|
for(BuildRequest req : player.buildQueue()){
|
||||||
|
if(test.test(req)) return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(BuildRequest req : selectRequests){
|
||||||
|
if(test.test(req)) return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void drawSelection(int x1, int y1, int x2, int y2){
|
||||||
|
NormalizeDrawResult result = PlaceUtils.normalizeDrawArea(Blocks.air, x1, y1, x2, y2, false, maxLength, 1f);
|
||||||
|
NormalizeResult dresult = PlaceUtils.normalizeArea(x1, y1, x2, y2, rotation, false, maxLength);
|
||||||
|
|
||||||
|
for(int x = dresult.x; x <= dresult.x2; x++){
|
||||||
|
for(int y = dresult.y; y <= dresult.y2; y++){
|
||||||
|
Tile tile = world.ltile(x, y);
|
||||||
|
if(tile == null || !validBreak(tile.x, tile.y)) continue;
|
||||||
|
|
||||||
|
drawBreaking(tile.x, tile.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tmp.r1.set(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
||||||
|
|
||||||
|
Draw.color(Pal.remove);
|
||||||
|
Lines.stroke(1f);
|
||||||
|
|
||||||
|
for(BuildRequest req : player.buildQueue()){
|
||||||
|
if(req.breaking) continue;
|
||||||
|
if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
||||||
|
drawBreaking(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
for(BuildRequest req : selectRequests){
|
||||||
|
if(req.breaking) continue;
|
||||||
|
if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
||||||
|
drawBreaking(req);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
for(BrokenBlock req : state.teams.get(player.getTeam()).brokenBlocks){
|
||||||
|
Block block = content.block(req.block);
|
||||||
|
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
|
||||||
|
drawSelected(req.x, req.y, content.block(req.block), Pal.remove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lines.stroke(2f);
|
||||||
|
|
||||||
|
Draw.color(Pal.removeBack);
|
||||||
|
Lines.rect(result.x, result.y - 1, result.x2 - result.x, result.y2 - result.y);
|
||||||
|
Draw.color(Pal.remove);
|
||||||
|
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void flushSelectRequests(Array<BuildRequest> requests){
|
||||||
|
for(BuildRequest req : requests){
|
||||||
|
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
|
||||||
|
selectRequests.add(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void flushRequests(Array<BuildRequest> requests){
|
||||||
|
for(BuildRequest req : requests){
|
||||||
|
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
|
||||||
|
player.addBuildRequest(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void drawRequest(BuildRequest request){
|
||||||
|
drawRequest(request.x, request.y, request.block, request.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Draws a placement icon for a specific block. */
|
||||||
|
protected void drawRequest(int x, int y, Block block, int rotation){
|
||||||
|
brequest.set(x, y, rotation, block);
|
||||||
|
brequest.animScale = 1f;
|
||||||
|
block.drawRequest(brequest, allRequests(), validPlace(x, y, block, rotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove everything from the queue in a selection. */
|
||||||
|
protected void removeSelection(int x1, int y1, int x2, int y2){
|
||||||
|
removeSelection(x1, y1, x2, y2, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove everything from the queue in a selection. */
|
||||||
|
protected void removeSelection(int x1, int y1, int x2, int y2, boolean flush){
|
||||||
|
NormalizeResult result = PlaceUtils.normalizeArea(x1, y1, x2, y2, rotation, false, maxLength);
|
||||||
|
for(int x = 0; x <= Math.abs(result.x2 - result.x); x++){
|
||||||
|
for(int y = 0; y <= Math.abs(result.y2 - result.y); y++){
|
||||||
|
int wx = x1 + x * Mathf.sign(x2 - x1);
|
||||||
|
int wy = y1 + y * Mathf.sign(y2 - y1);
|
||||||
|
|
||||||
|
Tile tile = world.ltile(wx, wy);
|
||||||
|
|
||||||
|
if(tile == null) continue;
|
||||||
|
|
||||||
|
if(!flush){
|
||||||
|
tryBreakBlock(wx, wy);
|
||||||
|
}else if(validBreak(tile.x, tile.y) && !selectRequests.contains(r -> r.tile() != null && r.tile().link() == tile)){
|
||||||
|
selectRequests.add(new BuildRequest(tile.x, tile.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove build requests
|
||||||
|
Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize);
|
||||||
|
|
||||||
|
Iterator<BuildRequest> it = player.buildQueue().iterator();
|
||||||
|
while(it.hasNext()){
|
||||||
|
BuildRequest req = it.next();
|
||||||
|
if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
it = selectRequests.iterator();
|
||||||
|
while(it.hasNext()){
|
||||||
|
BuildRequest req = it.next();
|
||||||
|
if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//remove blocks to rebuild
|
||||||
|
Iterator<BrokenBlock> broken = state.teams.get(player.getTeam()).brokenBlocks.iterator();
|
||||||
|
while(broken.hasNext()){
|
||||||
|
BrokenBlock req = broken.next();
|
||||||
|
Block block = content.block(req.block);
|
||||||
|
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
|
||||||
|
broken.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateLine(int x1, int y1, int x2, int y2){
|
||||||
|
lineRequests.clear();
|
||||||
|
iterateLine(x1, y1, x2, y2, l -> {
|
||||||
|
rotation = l.rotation;
|
||||||
|
BuildRequest req = new BuildRequest(l.x, l.y, l.rotation, block);
|
||||||
|
req.animScale = 1f;
|
||||||
|
lineRequests.add(req);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateLine(int x1, int y1){
|
||||||
|
updateLine(x1, y1, tileX(getMouseX()), tileY(getMouseY()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handles tile tap events that are not platform specific. */
|
/** Handles tile tap events that are not platform specific. */
|
||||||
@@ -214,12 +448,13 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
//clear when the player taps on something else
|
//clear when the player taps on something else
|
||||||
if(!consumed && !mobile && player.isBuilding() && block == null){
|
if(!consumed && !mobile && player.isBuilding() && block == null){
|
||||||
player.clearBuilding();
|
//player.clearBuilding();
|
||||||
block = null;
|
block = null;
|
||||||
return true;
|
return true;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if(!showedInventory){
|
if(!showedInventory){
|
||||||
frag.inv.hide();
|
frag.inv.hide();
|
||||||
@@ -301,16 +536,36 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
table.clear();
|
table.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(detector != null){
|
||||||
|
Core.input.removeProcessor(detector);
|
||||||
|
}
|
||||||
|
if(uiGroup != null){
|
||||||
|
uiGroup.remove();
|
||||||
|
uiGroup = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(){
|
public void add(){
|
||||||
|
Core.input.addProcessor(detector = new GestureDetector(20, 0.5f, 0.4f, 0.15f, this));
|
||||||
Core.input.addProcessor(this);
|
Core.input.addProcessor(this);
|
||||||
if(Core.scene != null){
|
if(Core.scene != null){
|
||||||
Table table = (Table)Core.scene.find("inputTable");
|
Table table = (Table)Core.scene.find("inputTable");
|
||||||
if(table != null){
|
if(table != null){
|
||||||
table.clear();
|
table.clear();
|
||||||
buildUI(table);
|
buildPlacementUI(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uiGroup = new WidgetGroup();
|
||||||
|
uiGroup.touchable(Touchable.childrenOnly);
|
||||||
|
uiGroup.setFillParent(true);
|
||||||
|
ui.hudGroup.addChild(uiGroup);
|
||||||
|
buildUI(uiGroup);
|
||||||
|
|
||||||
|
frag.add();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(player != null){
|
||||||
|
player.isBuilding = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,6 +611,15 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean validPlace(int x, int y, Block type, int rotation){
|
public boolean validPlace(int x, int y, Block type, int rotation){
|
||||||
|
return validPlace(x, y, type, rotation, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validPlace(int x, int y, Block type, int rotation, BuildRequest ignore){
|
||||||
|
for(BuildRequest req : player.buildQueue()){
|
||||||
|
if(req != ignore && !req.breaking && req.block.bounds(req.x, req.y, Tmp.r1).overlaps(type.bounds(x, y, Tmp.r2))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return Build.validPlace(player.getTeam(), x, y, type, rotation);
|
return Build.validPlace(player.getTeam(), x, y, type, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,13 +699,6 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PlaceDraw{
|
|
||||||
public int rotation, scalex, scaley;
|
|
||||||
public TextureRegion region;
|
|
||||||
|
|
||||||
public static final PlaceDraw instance = new PlaceDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
class PlaceLine{
|
class PlaceLine{
|
||||||
public int x, y, rotation;
|
public int x, y, rotation;
|
||||||
public boolean last;
|
public boolean last;
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package io.anuke.mindustry.input;
|
|||||||
|
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.graphics.*;
|
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.input.*;
|
|
||||||
import io.anuke.arc.input.GestureDetector.*;
|
import io.anuke.arc.input.GestureDetector.*;
|
||||||
|
import io.anuke.arc.input.*;
|
||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.math.geom.*;
|
import io.anuke.arc.math.geom.*;
|
||||||
|
import io.anuke.arc.scene.*;
|
||||||
import io.anuke.arc.scene.ui.layout.*;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
@@ -19,7 +19,6 @@ import io.anuke.mindustry.entities.type.*;
|
|||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.input.PlaceUtils.*;
|
|
||||||
import io.anuke.mindustry.ui.*;
|
import io.anuke.mindustry.ui.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
@@ -29,17 +28,15 @@ import static io.anuke.mindustry.input.PlaceMode.*;
|
|||||||
public class MobileInput extends InputHandler implements GestureListener{
|
public class MobileInput extends InputHandler implements GestureListener{
|
||||||
/** Maximum speed the player can pan. */
|
/** Maximum speed the player can pan. */
|
||||||
private static final float maxPanSpeed = 1.3f;
|
private static final float maxPanSpeed = 1.3f;
|
||||||
private static Rectangle r1 = new Rectangle(), r2 = new Rectangle();
|
|
||||||
/** Distance to edge of screen to start panning. */
|
/** Distance to edge of screen to start panning. */
|
||||||
private final float edgePan = Scl.scl(60f);
|
private final float edgePan = Scl.scl(60f);
|
||||||
|
|
||||||
//gesture data
|
//gesture data
|
||||||
private Vector2 vector = new Vector2();
|
private Vector2 vector = new Vector2();
|
||||||
private float lastZoom = -1;
|
private float lastZoom = -1;
|
||||||
private GestureDetector detector;
|
|
||||||
|
|
||||||
/** Position where the player started dragging a line. */
|
/** Position where the player started dragging a line. */
|
||||||
private int lineStartX, lineStartY;
|
private int lineStartX, lineStartY, lastLineX, lastLineY;
|
||||||
|
|
||||||
/** Animation scale for line. */
|
/** Animation scale for line. */
|
||||||
private float lineScale;
|
private float lineScale;
|
||||||
@@ -49,10 +46,8 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
/** Used for shifting build requests. */
|
/** Used for shifting build requests. */
|
||||||
private float shiftDeltaX, shiftDeltaY;
|
private float shiftDeltaX, shiftDeltaY;
|
||||||
|
|
||||||
/** List of currently selected tiles to place. */
|
|
||||||
private Array<PlaceRequest> selection = new Array<>();
|
|
||||||
/** Place requests to be removed. */
|
/** Place requests to be removed. */
|
||||||
private Array<PlaceRequest> removals = new Array<>();
|
private Array<BuildRequest> removals = new Array<>();
|
||||||
/** Whether or not the player is currently shifting all placed tiles. */
|
/** Whether or not the player is currently shifting all placed tiles. */
|
||||||
private boolean selecting;
|
private boolean selecting;
|
||||||
/** Whether the player is currently in line-place mode. */
|
/** Whether the player is currently in line-place mode. */
|
||||||
@@ -62,9 +57,9 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
/** Whether no recipe was available when switching to break mode. */
|
/** Whether no recipe was available when switching to break mode. */
|
||||||
private Block lastBlock;
|
private Block lastBlock;
|
||||||
/** Last placed request. Used for drawing block overlay. */
|
/** Last placed request. Used for drawing block overlay. */
|
||||||
private PlaceRequest lastPlaced;
|
private BuildRequest lastPlaced;
|
||||||
|
/** Down tracking for panning.*/
|
||||||
private int prevX, prevY, prevRotation;
|
private boolean down = false;
|
||||||
|
|
||||||
//region utility methods
|
//region utility methods
|
||||||
|
|
||||||
@@ -99,10 +94,10 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
r2.setSize(block.size * tilesize);
|
r2.setSize(block.size * tilesize);
|
||||||
r2.setCenter(x * tilesize + block.offset(), y * tilesize + block.offset());
|
r2.setCenter(x * tilesize + block.offset(), y * tilesize + block.offset());
|
||||||
|
|
||||||
for(PlaceRequest req : selection){
|
for(BuildRequest req : selectRequests){
|
||||||
Tile other = req.tile();
|
Tile other = req.tile();
|
||||||
|
|
||||||
if(other == null || req.remove) continue;
|
if(other == null || req.breaking) continue;
|
||||||
|
|
||||||
r1.setSize(req.block.size * tilesize);
|
r1.setSize(req.block.size * tilesize);
|
||||||
r1.setCenter(other.worldx() + req.block.offset(), other.worldy() + req.block.offset());
|
r1.setCenter(other.worldx() + req.block.offset(), other.worldy() + req.block.offset());
|
||||||
@@ -128,16 +123,16 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the selection request that overlaps this tile, or null. */
|
/** Returns the selection request that overlaps this tile, or null. */
|
||||||
PlaceRequest getRequest(Tile tile){
|
BuildRequest getRequest(Tile tile){
|
||||||
r2.setSize(tilesize);
|
r2.setSize(tilesize);
|
||||||
r2.setCenter(tile.worldx(), tile.worldy());
|
r2.setCenter(tile.worldx(), tile.worldy());
|
||||||
|
|
||||||
for(PlaceRequest req : selection){
|
for(BuildRequest req : selectRequests){
|
||||||
Tile other = req.tile();
|
Tile other = req.tile();
|
||||||
|
|
||||||
if(other == null) continue;
|
if(other == null) continue;
|
||||||
|
|
||||||
if(!req.remove){
|
if(!req.breaking){
|
||||||
r1.setSize(req.block.size * tilesize);
|
r1.setSize(req.block.size * tilesize);
|
||||||
r1.setCenter(other.worldx() + req.block.offset(), other.worldy() + req.block.offset());
|
r1.setCenter(other.worldx() + req.block.offset(), other.worldy() + req.block.offset());
|
||||||
|
|
||||||
@@ -156,8 +151,8 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeRequest(PlaceRequest request){
|
void removeRequest(BuildRequest request){
|
||||||
selection.removeValue(request, true);
|
selectRequests.removeValue(request, true);
|
||||||
removals.add(request);
|
removals.add(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,80 +167,8 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
//endregion
|
//endregion
|
||||||
//region UI and drawing
|
//region UI and drawing
|
||||||
|
|
||||||
void drawRequest(PlaceRequest request, PlaceRequest prev){
|
|
||||||
Tile tile = request.tile();
|
|
||||||
|
|
||||||
if(!request.remove){
|
|
||||||
if(prev != null){
|
|
||||||
request.block.getPlaceDraw(placeDraw, request.rotation, prev.x - request.x, prev.y - request.y, prev.rotation);
|
|
||||||
}else{
|
|
||||||
request.block.getPlaceDraw(placeDraw, request.rotation, 0, 0, request.rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
//draw placing request
|
|
||||||
float offset = request.block.offset();
|
|
||||||
TextureRegion region = placeDraw.region;
|
|
||||||
|
|
||||||
Draw.mixcol(Pal.accent, Mathf.clamp((1f - request.scale) / 0.5f + 0.12f + Mathf.absin(Time.time(), 8f, 0.35f)));
|
|
||||||
Draw.tint(Color.white, Pal.breakInvalid, request.redness);
|
|
||||||
|
|
||||||
Draw.rect(region, tile.worldx() + offset, tile.worldy() + offset,
|
|
||||||
region.getWidth() * request.scale * Draw.scl * placeDraw.scalex,
|
|
||||||
region.getHeight() * request.scale * Draw.scl * placeDraw.scaley,
|
|
||||||
request.block.rotate ? placeDraw.rotation * 90 : 0);
|
|
||||||
|
|
||||||
Draw.mixcol(Pal.accent, 1f);
|
|
||||||
for(int i = 0; i < 4; i++){
|
|
||||||
Point2 p = Geometry.d8edge[i];
|
|
||||||
float poffset = -Math.max(request.block.size - 1, 0) / 2f * tilesize;
|
|
||||||
TextureRegion find = Core.atlas.find("block-select");
|
|
||||||
if(i % 2 == 0)
|
|
||||||
Draw.rect("block-select", request.tile().x * tilesize + request.block.offset() + poffset * p.x, request.tile().y * tilesize + request.block.offset() + poffset * p.y,
|
|
||||||
find.getWidth() * Draw.scl * request.scale, find.getHeight() * Draw.scl * request.scale, i * 90);
|
|
||||||
}
|
|
||||||
Draw.color();
|
|
||||||
}else{
|
|
||||||
float rad = Math.max((tile.block().size * tilesize / 2f - 1) * request.scale, 1f);
|
|
||||||
|
|
||||||
if(rad <= 1.01f) return;
|
|
||||||
Draw.mixcol();
|
|
||||||
//draw removing request
|
|
||||||
Draw.tint(Pal.removeBack);
|
|
||||||
Lines.square(tile.drawx(), tile.drawy() - 1, rad);
|
|
||||||
Draw.tint(Pal.remove);
|
|
||||||
Lines.square(tile.drawx(), tile.drawy(), rad);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Draws a placement icon for a specific block. */
|
|
||||||
void drawPlace(int x, int y, Block block, int rotation, int prevX, int prevY, int prevRotation){
|
|
||||||
if(validPlace(x, y, block, rotation) && !checkOverlapPlacement(x, y, block)){
|
|
||||||
block.getPlaceDraw(placeDraw, rotation, prevX, prevY, prevRotation);
|
|
||||||
|
|
||||||
Draw.color();
|
|
||||||
Draw.rect(placeDraw.region, x * tilesize + block.offset(), y * tilesize + block.offset(),
|
|
||||||
placeDraw.region.getWidth() * Draw.scl * placeDraw.scalex,
|
|
||||||
placeDraw.region.getHeight() * Draw.scl * placeDraw.scaley,
|
|
||||||
block.rotate ? placeDraw.rotation * 90 : 0);
|
|
||||||
|
|
||||||
Draw.color(Pal.accent);
|
|
||||||
for(int i = 0; i < 4; i++){
|
|
||||||
Point2 p = Geometry.d8edge[i];
|
|
||||||
float offset = -Math.max(block.size - 1, 0) / 2f * tilesize;
|
|
||||||
if(i % 2 == 0)
|
|
||||||
Draw.rect("block-select", x * tilesize + block.offset() + offset * p.x, y * tilesize + block.offset() + offset * p.y, i * 90);
|
|
||||||
}
|
|
||||||
Draw.color();
|
|
||||||
}else{
|
|
||||||
Draw.color(Pal.removeBack);
|
|
||||||
Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset() - 1, block.size * tilesize / 2f - 1);
|
|
||||||
Draw.color(Pal.remove);
|
|
||||||
Lines.square(x * tilesize + block.offset(), y * tilesize + block.offset(), block.size * tilesize / 2f - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildUI(Table table){
|
public void buildPlacementUI(Table table){
|
||||||
table.addImage().color(Pal.gray).height(4f).colspan(4).growX();
|
table.addImage().color(Pal.gray).height(4f).colspan(4).growX();
|
||||||
table.row();
|
table.row();
|
||||||
table.left().margin(0f).defaults().size(48f);
|
table.left().margin(0f).defaults().size(48f);
|
||||||
@@ -267,12 +190,12 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
|
|
||||||
//confirm button
|
//confirm button
|
||||||
table.addImageButton(Icon.checkSmall, Styles.clearPartiali, () -> {
|
table.addImageButton(Icon.checkSmall, Styles.clearPartiali, () -> {
|
||||||
for(PlaceRequest request : selection){
|
for(BuildRequest request : selectRequests){
|
||||||
Tile tile = request.tile();
|
Tile tile = request.tile();
|
||||||
|
|
||||||
//actually place/break all selected blocks
|
//actually place/break all selected blocks
|
||||||
if(tile != null){
|
if(tile != null){
|
||||||
if(!request.remove){
|
if(!request.breaking){
|
||||||
rotation = request.rotation;
|
rotation = request.rotation;
|
||||||
Block before = block;
|
Block before = block;
|
||||||
block = request.block;
|
block = request.block;
|
||||||
@@ -285,82 +208,83 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//move all current requests to removal array so they fade out
|
//move all current requests to removal array so they fade out
|
||||||
removals.addAll(selection);
|
removals.addAll(selectRequests.find(r -> !r.breaking));
|
||||||
selection.clear();
|
selectRequests.clear();
|
||||||
selecting = false;
|
selecting = false;
|
||||||
}).visible(() -> !selection.isEmpty()).name("confirmplace");
|
}).visible(() -> !selectRequests.isEmpty()).name("confirmplace");
|
||||||
|
}
|
||||||
|
|
||||||
Core.scene.table(t -> {
|
@Override
|
||||||
t.setName("cancelMobile");
|
public void buildUI(Group group){
|
||||||
t.bottom().left().visible(() -> (player.isBuilding() || block != null || mode == breaking) && !state.is(State.menu));
|
group.fill(t -> {
|
||||||
|
t.bottom().left().visible(() -> (player.isBuilding() || block != null || mode == breaking || !selectRequests.isEmpty()) && !state.is(State.menu));
|
||||||
t.addImageTextButton("$cancel", Icon.cancelSmall, () -> {
|
t.addImageTextButton("$cancel", Icon.cancelSmall, () -> {
|
||||||
player.clearBuilding();
|
player.clearBuilding();
|
||||||
|
selectRequests.clear();
|
||||||
mode = none;
|
mode = none;
|
||||||
block = null;
|
block = null;
|
||||||
}).width(155f);
|
}).width(155f);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDrawing(){
|
|
||||||
return selection.size > 0 || removals.size > 0 || lineMode || player.target != null || mode != PlaceMode.none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlacing(){
|
public boolean isPlacing(){
|
||||||
return super.isPlacing() && mode == placing;
|
return super.isPlacing() && mode == placing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawOutlined(){
|
public void drawBottom(){
|
||||||
Lines.stroke(1f);
|
Lines.stroke(1f);
|
||||||
|
|
||||||
//draw removals
|
//draw removals
|
||||||
for(PlaceRequest request : removals){
|
for(BuildRequest request : removals){
|
||||||
Tile tile = request.tile();
|
Tile tile = request.tile();
|
||||||
|
|
||||||
if(tile == null) continue;
|
if(tile == null) continue;
|
||||||
|
|
||||||
request.scale = Mathf.lerpDelta(request.scale, 0f, 0.2f);
|
request.animScale = Mathf.lerpDelta(request.animScale, 0f, 0.2f);
|
||||||
request.redness = Mathf.lerpDelta(request.redness, 0f, 0.2f);
|
request.animInvalid = Mathf.lerpDelta(request.animInvalid, 0f, 0.2f);
|
||||||
|
|
||||||
drawRequest(request, null);
|
if(request.breaking){
|
||||||
|
drawSelected(request.x, request.y, tile.block(), Pal.remove);
|
||||||
|
}else{
|
||||||
|
request.block.drawRequest(request, allRequests(), true);
|
||||||
|
}
|
||||||
|
//TODO
|
||||||
|
//drawRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaceRequest last = null;
|
|
||||||
|
|
||||||
//draw list of requests
|
//draw list of requests
|
||||||
for(PlaceRequest request : selection){
|
for(BuildRequest request : selectRequests){
|
||||||
Tile tile = request.tile();
|
Tile tile = request.tile();
|
||||||
|
|
||||||
if(tile == null) continue;
|
if(tile == null) continue;
|
||||||
|
|
||||||
if((!request.remove && validPlace(tile.x, tile.y, request.block, request.rotation))
|
if((!request.breaking && validPlace(tile.x, tile.y, request.block, request.rotation))
|
||||||
|| (request.remove && validBreak(tile.x, tile.y))){
|
|| (request.breaking && validBreak(tile.x, tile.y))){
|
||||||
request.scale = Mathf.lerpDelta(request.scale, 1f, 0.2f);
|
request.animScale = Mathf.lerpDelta(request.animScale, 1f, 0.2f);
|
||||||
request.redness = Mathf.lerpDelta(request.redness, 0f, 0.2f);
|
request.animInvalid = Mathf.lerpDelta(request.animInvalid, 0f, 0.2f);
|
||||||
}else{
|
}else{
|
||||||
request.scale = Mathf.lerpDelta(request.scale, 0.6f, 0.1f);
|
request.animScale = Mathf.lerpDelta(request.animScale, 0.6f, 0.1f);
|
||||||
request.redness = Mathf.lerpDelta(request.redness, 0.9f, 0.2f);
|
request.animInvalid = Mathf.lerpDelta(request.animInvalid, 0.9f, 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tmp.c1.set(Draw.getMixColor());
|
Tmp.c1.set(Draw.getMixColor());
|
||||||
|
|
||||||
if(!request.remove && request == lastPlaced && request.block != null){
|
if(!request.breaking && request == lastPlaced && request.block != null){
|
||||||
Draw.mixcol();
|
Draw.mixcol();
|
||||||
if(request.block.rotate) drawArrow(request.block, tile.x, tile.y, request.rotation);
|
if(request.block.rotate) drawArrow(request.block, tile.x, tile.y, request.rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.mixcol(Tmp.c1, 1f);
|
//Draw.mixcol(Tmp.c1, 1f);
|
||||||
drawRequest(request, last);
|
Draw.reset();
|
||||||
|
drawRequest(request);
|
||||||
|
|
||||||
//draw last placed request
|
//draw last placed request
|
||||||
if(!request.remove && request == lastPlaced && request.block != null){
|
if(!request.breaking && request == lastPlaced && request.block != null){
|
||||||
Draw.mixcol();
|
Draw.mixcol();
|
||||||
request.block.drawPlace(tile.x, tile.y, rotation, validPlace(tile.x, tile.y, request.block, rotation));
|
request.block.drawPlace(tile.x, tile.y, rotation, validPlace(tile.x, tile.y, request.block, rotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
last = request;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.mixcol();
|
Draw.mixcol();
|
||||||
@@ -373,48 +297,18 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
|
|
||||||
if(mode == placing && block != null){
|
if(mode == placing && block != null){
|
||||||
//draw placing
|
//draw placing
|
||||||
|
for(int i = 0; i < lineRequests.size; i++){
|
||||||
prevX = lineStartX;
|
BuildRequest req = lineRequests.get(i);
|
||||||
prevY = lineStartY;
|
if(i == lineRequests.size - 1 && req.block.rotate){
|
||||||
prevRotation = rotation;
|
drawArrow(block, req.x, req.y, req.rotation);
|
||||||
|
}
|
||||||
iterateLine(lineStartX, lineStartY, tileX, tileY, l -> {
|
drawRequest(lineRequests.get(i));
|
||||||
if(l.last && block.rotate){
|
|
||||||
drawArrow(block, l.x, l.y, l.rotation);
|
|
||||||
}
|
}
|
||||||
drawPlace(l.x, l.y, block, l.rotation, prevX - l.x, prevY - l.y, prevRotation);
|
|
||||||
|
|
||||||
rotation = l.rotation;
|
|
||||||
prevX = l.x;
|
|
||||||
prevY = l.y;
|
|
||||||
prevRotation = l.rotation;
|
|
||||||
});
|
|
||||||
}else if(mode == breaking){
|
}else if(mode == breaking){
|
||||||
//draw breaking
|
drawSelection(lineStartX, lineStartY, tileX, tileY);
|
||||||
NormalizeDrawResult result = PlaceUtils.normalizeDrawArea(Blocks.air, lineStartX, lineStartY, tileX, tileY, false, maxLength, 1f);
|
|
||||||
NormalizeResult dresult = PlaceUtils.normalizeArea(lineStartX, lineStartY, tileX, tileY, rotation, false, maxLength);
|
|
||||||
|
|
||||||
for(int x = dresult.x; x <= dresult.x2; x++){
|
|
||||||
for(int y = dresult.y; y <= dresult.y2; y++){
|
|
||||||
Tile other = world.ltile(x, y);
|
|
||||||
if(other == null || !validBreak(other.x, other.y)) continue;
|
|
||||||
|
|
||||||
Draw.color(Pal.removeBack);
|
|
||||||
Lines.square(other.drawx(), other.drawy() - 1, other.block().size * tilesize / 2f - 1);
|
|
||||||
Draw.color(Pal.remove);
|
|
||||||
Lines.square(other.drawx(), other.drawy(), other.block().size * tilesize / 2f - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.color(Pal.removeBack);
|
|
||||||
Lines.rect(result.x, result.y - 1, result.x2 - result.x, result.y2 - result.y);
|
|
||||||
Draw.color(Pal.remove);
|
|
||||||
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetTrait target = player.target;
|
TargetTrait target = player.target;
|
||||||
|
|
||||||
//draw targeting crosshair
|
//draw targeting crosshair
|
||||||
@@ -438,31 +332,28 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawRequest(BuildRequest request){
|
||||||
|
if(request.tile() == null) return;
|
||||||
|
brequest.animScale = request.animScale = Mathf.lerpDelta(request.animScale, 1f, 0.1f);
|
||||||
|
|
||||||
|
if(request.breaking){
|
||||||
|
drawSelected(request.x, request.y, request.tile().block(), Pal.remove);
|
||||||
|
}else{
|
||||||
|
drawRequest(request.x, request.y, request.block, request.rotation);
|
||||||
|
drawSelected(request.x, request.y, request.block, Pal.accent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region input events
|
//region input events
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(){
|
|
||||||
Core.input.addProcessor(detector = new GestureDetector(20, 0.5f, 0.4f, 0.15f, this));
|
|
||||||
super.add();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove(){
|
|
||||||
super.remove();
|
|
||||||
if(detector != null){
|
|
||||||
Core.input.removeProcessor(detector);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Core.scene != null && Core.scene.find("cancelMobile") != null){
|
|
||||||
Core.scene.find("cancelMobile").remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean touchDown(int screenX, int screenY, int pointer, KeyCode button){
|
public boolean touchDown(int screenX, int screenY, int pointer, KeyCode button){
|
||||||
if(state.is(State.menu) || player.isDead()) return false;
|
if(state.is(State.menu) || player.isDead()) return false;
|
||||||
|
|
||||||
|
down = true;
|
||||||
|
|
||||||
//get tile on cursor
|
//get tile on cursor
|
||||||
Tile cursor = tileAt(screenX, screenY);
|
Tile cursor = tileAt(screenX, screenY);
|
||||||
|
|
||||||
@@ -489,44 +380,20 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
public boolean touchUp(int screenX, int screenY, int pointer, KeyCode button){
|
public boolean touchUp(int screenX, int screenY, int pointer, KeyCode button){
|
||||||
lastZoom = renderer.getScale();
|
lastZoom = renderer.getScale();
|
||||||
|
|
||||||
|
if(!Core.input.isTouched()){
|
||||||
|
down = false;
|
||||||
|
}
|
||||||
|
|
||||||
//place down a line if in line mode
|
//place down a line if in line mode
|
||||||
if(lineMode){
|
if(lineMode){
|
||||||
int tileX = tileX(screenX);
|
int tileX = tileX(screenX);
|
||||||
int tileY = tileY(screenY);
|
int tileY = tileY(screenY);
|
||||||
|
|
||||||
if(mode == placing && isPlacing()){
|
if(mode == placing && isPlacing()){
|
||||||
iterateLine(lineStartX, lineStartY, tileX, tileY, l -> {
|
flushSelectRequests(lineRequests);
|
||||||
Tile tile = world.tile(l.x, l.y);
|
|
||||||
if(tile != null && checkOverlapPlacement(tile.x, tile.y, block)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlaceRequest request = new PlaceRequest(l.x, l.y, block, l.rotation);
|
|
||||||
request.scale = 1f;
|
|
||||||
selection.add(request);
|
|
||||||
});
|
|
||||||
Events.fire(new LineConfirmEvent());
|
Events.fire(new LineConfirmEvent());
|
||||||
}else if(mode == breaking){
|
}else if(mode == breaking){
|
||||||
//normalize area
|
removeSelection(lineStartX, lineStartY, tileX, tileY, true);
|
||||||
NormalizeResult result = PlaceUtils.normalizeArea(lineStartX, lineStartY, tileX, tileY, rotation, false, maxLength);
|
|
||||||
|
|
||||||
//break everything in area
|
|
||||||
for(int x = 0; x <= Math.abs(result.x2 - result.x); x++){
|
|
||||||
for(int y = 0; y <= Math.abs(result.y2 - result.y); y++){
|
|
||||||
int wx = lineStartX + x * Mathf.sign(tileX - lineStartX);
|
|
||||||
int wy = lineStartY + y * Mathf.sign(tileY - lineStartY);
|
|
||||||
|
|
||||||
Tile tar = world.ltile(wx, wy);
|
|
||||||
|
|
||||||
if(tar == null) continue;
|
|
||||||
|
|
||||||
if(!hasRequest(world.tile(tar.x, tar.y)) && validBreak(tar.x, tar.y)){
|
|
||||||
PlaceRequest request = new PlaceRequest(tar.x, tar.y);
|
|
||||||
request.scale = 1f;
|
|
||||||
selection.add(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lineMode = false;
|
lineMode = false;
|
||||||
@@ -554,11 +421,14 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
//long pressing enables line mode otherwise
|
//long pressing enables line mode otherwise
|
||||||
lineStartX = cursor.x;
|
lineStartX = cursor.x;
|
||||||
lineStartY = cursor.y;
|
lineStartY = cursor.y;
|
||||||
|
lastLineX = cursor.x;
|
||||||
|
lastLineY = cursor.y;
|
||||||
lineMode = true;
|
lineMode = true;
|
||||||
|
|
||||||
if(mode == breaking){
|
if(mode == breaking){
|
||||||
Effects.effect(Fx.tapBlock, cursor.worldx(), cursor.worldy(), 1f);
|
Effects.effect(Fx.tapBlock, cursor.worldx(), cursor.worldy(), 1f);
|
||||||
}else if(block != null){
|
}else if(block != null){
|
||||||
|
updateLine(lineStartX, lineStartY, cursor.x, cursor.y);
|
||||||
Effects.effect(Fx.tapBlock, cursor.worldx() + block.offset(), cursor.worldy() + block.offset(), block.size);
|
Effects.effect(Fx.tapBlock, cursor.worldx() + block.offset(), cursor.worldy() + block.offset(), block.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,11 +454,11 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
removeRequest(getRequest(cursor));
|
removeRequest(getRequest(cursor));
|
||||||
}else if(mode == placing && isPlacing() && validPlace(cursor.x, cursor.y, block, rotation) && !checkOverlapPlacement(cursor.x, cursor.y, block)){
|
}else if(mode == placing && isPlacing() && validPlace(cursor.x, cursor.y, block, rotation) && !checkOverlapPlacement(cursor.x, cursor.y, block)){
|
||||||
//add to selection queue if it's a valid place position
|
//add to selection queue if it's a valid place position
|
||||||
selection.add(lastPlaced = new PlaceRequest(cursor.x, cursor.y, block, rotation));
|
selectRequests.add(lastPlaced = new BuildRequest(cursor.x, cursor.y, rotation, block));
|
||||||
}else if(mode == breaking && validBreak(cursor.link().x, cursor.link().y) && !hasRequest(cursor.link())){
|
}else if(mode == breaking && validBreak(cursor.link().x, cursor.link().y) && !hasRequest(cursor.link())){
|
||||||
//add to selection queue if it's a valid BREAK position
|
//add to selection queue if it's a valid BREAK position
|
||||||
cursor = cursor.link();
|
cursor = cursor.link();
|
||||||
selection.add(new PlaceRequest(cursor.x, cursor.y));
|
selectRequests.add(new BuildRequest(cursor.x, cursor.y));
|
||||||
}else if(!canTapPlayer(worldx, worldy) && !tileTapped(cursor.link())){
|
}else if(!canTapPlayer(worldx, worldy) && !tileTapped(cursor.link())){
|
||||||
tryBeginMine(cursor);
|
tryBeginMine(cursor);
|
||||||
}
|
}
|
||||||
@@ -598,12 +468,16 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
if(state.is(State.menu) || player.isDead()){
|
if(state.is(State.menu) ){
|
||||||
selection.clear();
|
selectRequests.clear();
|
||||||
removals.clear();
|
removals.clear();
|
||||||
mode = none;
|
mode = none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(player.isDead()){
|
||||||
|
mode = none;
|
||||||
|
}
|
||||||
|
|
||||||
//zoom things
|
//zoom things
|
||||||
if(Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && (Core.input.keyDown(Binding.zoom_hold))){
|
if(Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && (Core.input.keyDown(Binding.zoom_hold))){
|
||||||
renderer.scaleCamera(Core.input.axisTap(Binding.zoom));
|
renderer.scaleCamera(Core.input.axisTap(Binding.zoom));
|
||||||
@@ -629,8 +503,6 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
if(mode == none){
|
if(mode == none){
|
||||||
selecting = false;
|
selecting = false;
|
||||||
lineMode = false;
|
lineMode = false;
|
||||||
removals.addAll(selection);
|
|
||||||
selection.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lineMode && mode == placing && block == null){
|
if(lineMode && mode == placing && block == null){
|
||||||
@@ -656,7 +528,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
lineScale = Mathf.lerpDelta(lineScale, 1f, 0.1f);
|
lineScale = Mathf.lerpDelta(lineScale, 1f, 0.1f);
|
||||||
|
|
||||||
//When in line mode, pan when near screen edges automatically
|
//When in line mode, pan when near screen edges automatically
|
||||||
if(Core.input.isTouched(0) && lineMode){
|
if(Core.input.isTouched(0)){
|
||||||
float screenX = Core.input.mouseX(), screenY = Core.input.mouseY();
|
float screenX = Core.input.mouseX(), screenY = Core.input.mouseY();
|
||||||
|
|
||||||
float panX = 0, panY = 0;
|
float panX = 0, panY = 0;
|
||||||
@@ -684,15 +556,24 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
Core.camera.position.x += vector.x;
|
Core.camera.position.x += vector.x;
|
||||||
Core.camera.position.y += vector.y;
|
Core.camera.position.y += vector.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lx = tileX(Core.input.mouseX()), ly = tileY(Core.input.mouseY());
|
||||||
|
|
||||||
|
if((lastLineX != lx || lastLineY != ly) && isPlacing()){
|
||||||
|
lastLineX = lx;
|
||||||
|
lastLineY = ly;
|
||||||
|
updateLine(lineStartX, lineStartY, lx, ly);
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
|
lineRequests.clear();
|
||||||
lineScale = 0f;
|
lineScale = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove place requests that have disappeared
|
//remove place requests that have disappeared
|
||||||
for(int i = removals.size - 1; i >= 0; i--){
|
for(int i = removals.size - 1; i >= 0; i--){
|
||||||
PlaceRequest request = removals.get(i);
|
BuildRequest request = removals.get(i);
|
||||||
|
|
||||||
if(request.scale <= 0.0001f){
|
if(request.animScale <= 0.0001f){
|
||||||
removals.remove(i);
|
removals.remove(i);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
@@ -712,6 +593,8 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!down) return false;
|
||||||
|
|
||||||
if(selecting){ //pan all requests
|
if(selecting){ //pan all requests
|
||||||
shiftDeltaX += deltaX;
|
shiftDeltaX += deltaX;
|
||||||
shiftDeltaY += deltaY;
|
shiftDeltaY += deltaY;
|
||||||
@@ -720,8 +603,8 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
int shiftedY = (int)(shiftDeltaY / tilesize);
|
int shiftedY = (int)(shiftDeltaY / tilesize);
|
||||||
|
|
||||||
if(Math.abs(shiftedX) > 0 || Math.abs(shiftedY) > 0){
|
if(Math.abs(shiftedX) > 0 || Math.abs(shiftedY) > 0){
|
||||||
for(PlaceRequest req : selection){
|
for(BuildRequest req : selectRequests){
|
||||||
if(req.remove) continue; //don't shift removal requests
|
if(req.breaking) continue; //don't shift removal requests
|
||||||
req.x += shiftedX;
|
req.x += shiftedX;
|
||||||
req.y += shiftedY;
|
req.y += shiftedY;
|
||||||
}
|
}
|
||||||
@@ -756,33 +639,4 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
private class PlaceRequest{
|
|
||||||
int x, y;
|
|
||||||
Block block;
|
|
||||||
int rotation;
|
|
||||||
boolean remove;
|
|
||||||
|
|
||||||
//animation variables
|
|
||||||
float scale;
|
|
||||||
float redness;
|
|
||||||
|
|
||||||
PlaceRequest(int x, int y, Block block, int rotation){
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.block = block;
|
|
||||||
this.rotation = rotation;
|
|
||||||
this.remove = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlaceRequest(int x, int y){
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.remove = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Tile tile(){
|
|
||||||
return world.tile(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
|||||||
TeamData data = state.teams.get(team);
|
TeamData data = state.teams.get(team);
|
||||||
int blocks = stream.readInt();
|
int blocks = stream.readInt();
|
||||||
for(int j = 0; j < blocks; j++){
|
for(int j = 0; j < blocks; j++){
|
||||||
data.brokenBlocks.addLast(new BrokenBlock(stream.readShort(), stream.readShort(), stream.readShort(), stream.readShort(), stream.readInt()));
|
data.brokenBlocks.addLast(new BrokenBlock(stream.readShort(), stream.readShort(), stream.readShort(), content.block(stream.readShort()).id, stream.readInt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ package io.anuke.mindustry.mod;
|
|||||||
|
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.audio.*;
|
import io.anuke.arc.audio.*;
|
||||||
|
import io.anuke.arc.collection.Array;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
|
import io.anuke.arc.files.*;
|
||||||
import io.anuke.arc.function.*;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.util.ArcAnnotate.*;
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
|
import io.anuke.arc.util.reflect.Field;
|
||||||
import io.anuke.arc.util.reflect.*;
|
import io.anuke.arc.util.reflect.*;
|
||||||
import io.anuke.arc.util.serialization.*;
|
import io.anuke.arc.util.serialization.*;
|
||||||
import io.anuke.arc.util.serialization.Json.*;
|
import io.anuke.arc.util.serialization.Json.*;
|
||||||
@@ -16,10 +19,14 @@ import io.anuke.mindustry.entities.Effects.*;
|
|||||||
import io.anuke.mindustry.entities.bullet.*;
|
import io.anuke.mindustry.entities.bullet.*;
|
||||||
import io.anuke.mindustry.entities.type.*;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
|
import io.anuke.mindustry.game.Objectives.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.mod.Mods.*;
|
import io.anuke.mindustry.mod.Mods.*;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
import io.anuke.mindustry.world.consumers.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ContentParser{
|
public class ContentParser{
|
||||||
@@ -29,7 +36,15 @@ public class ContentParser{
|
|||||||
put(BulletType.class, (type, data) -> field(Bullets.class, data));
|
put(BulletType.class, (type, data) -> field(Bullets.class, data));
|
||||||
put(Effect.class, (type, data) -> field(Fx.class, data));
|
put(Effect.class, (type, data) -> field(Fx.class, data));
|
||||||
put(StatusEffect.class, (type, data) -> field(StatusEffects.class, data));
|
put(StatusEffect.class, (type, data) -> field(StatusEffects.class, data));
|
||||||
|
put(Loadout.class, (type, data) -> field(Loadouts.class, data));
|
||||||
put(Color.class, (type, data) -> Color.valueOf(data.asString()));
|
put(Color.class, (type, data) -> Color.valueOf(data.asString()));
|
||||||
|
put(BulletType.class, (type, data) -> {
|
||||||
|
Class<? extends BulletType> bc = data.has("type") ? resolve(data.getString("type"), "io.anuke.mindustry.entities.bullets") : BasicBulletType.class;
|
||||||
|
data.remove("type");
|
||||||
|
BulletType result = make(bc);
|
||||||
|
readFields(result, data);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
put(Music.class, (type, data) -> {
|
put(Music.class, (type, data) -> {
|
||||||
if(fieldOpt(Musics.class, data) != null) return fieldOpt(Musics.class, data);
|
if(fieldOpt(Musics.class, data) != null) return fieldOpt(Musics.class, data);
|
||||||
|
|
||||||
@@ -47,17 +62,30 @@ public class ContentParser{
|
|||||||
Log.info(Core.assets.get(path));
|
Log.info(Core.assets.get(path));
|
||||||
return Core.assets.get(path);
|
return Core.assets.get(path);
|
||||||
});
|
});
|
||||||
|
put(Objective.class, (type, data) -> {
|
||||||
|
Class<? extends Objective> oc = data.has("type") ? resolve(data.getString("type"), "io.anuke.mindustry.game.Objectives") : ZoneWave.class;
|
||||||
|
data.remove("type");
|
||||||
|
Objective obj = make(oc);
|
||||||
|
readFields(obj, data);
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
}};
|
}};
|
||||||
/** Stores things that need to be parsed fully, e.g. reading fields of content.
|
/** Stores things that need to be parsed fully, e.g. reading fields of content.
|
||||||
* This is done to accomodate binding of content names first.*/
|
* This is done to accomodate binding of content names first.*/
|
||||||
private Array<Runnable> reads = new Array<>();
|
private Array<Runnable> reads = new Array<>();
|
||||||
private LoadedMod currentMod;
|
private LoadedMod currentMod;
|
||||||
|
private Content currentContent;
|
||||||
|
|
||||||
private Json parser = new Json(){
|
private Json parser = new Json(){
|
||||||
public <T> T readValue(Class<T> type, Class elementType, JsonValue jsonData){
|
@Override
|
||||||
|
public <T> T readValue(Class<T> type, Class elementType, JsonValue jsonData, Class keyType){
|
||||||
if(type != null){
|
if(type != null){
|
||||||
if(classParsers.containsKey(type)){
|
if(classParsers.containsKey(type)){
|
||||||
|
try{
|
||||||
return (T)classParsers.get(type).parse(type, jsonData);
|
return (T)classParsers.get(type).parse(type, jsonData);
|
||||||
|
}catch(Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Content.class.isAssignableFrom(type)){
|
if(Content.class.isAssignableFrom(type)){
|
||||||
@@ -65,16 +93,30 @@ public class ContentParser{
|
|||||||
String prefix = currentMod != null ? currentMod.name + "-" : "";
|
String prefix = currentMod != null ? currentMod.name + "-" : "";
|
||||||
T one = (T)Vars.content.getByName(ctype, prefix + jsonData.asString());
|
T one = (T)Vars.content.getByName(ctype, prefix + jsonData.asString());
|
||||||
if(one != null) return one;
|
if(one != null) return one;
|
||||||
return (T)Vars.content.getByName(ctype, jsonData.asString());
|
T two = (T)Vars.content.getByName(ctype, jsonData.asString());
|
||||||
|
|
||||||
|
if(two != null) return two;
|
||||||
|
throw new IllegalArgumentException("\"" + jsonData.name + "\": No " + ctype + " found with name '" + jsonData.asString() + "'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.readValue(type, elementType, jsonData);
|
return super.readValue(type, elementType, jsonData, keyType);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private ObjectMap<ContentType, TypeParser<?>> parsers = ObjectMap.of(
|
private ObjectMap<ContentType, TypeParser<?>> parsers = ObjectMap.of(
|
||||||
ContentType.block, (TypeParser<Block>)(mod, name, value) -> {
|
ContentType.block, (TypeParser<Block>)(mod, name, value) -> {
|
||||||
|
readBundle(ContentType.block, name, value);
|
||||||
|
|
||||||
|
Block block;
|
||||||
|
|
||||||
|
if(Vars.content.getByName(ContentType.block, name) != null){
|
||||||
|
block = Vars.content.getByName(ContentType.block, name);
|
||||||
|
|
||||||
|
if(value.has("type")){
|
||||||
|
throw new IllegalArgumentException("When overwriting an existing block, you must not re-declared its type. The original type will be used. Block: " + name);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
//TODO generate dynamically instead of doing.. this
|
//TODO generate dynamically instead of doing.. this
|
||||||
Class<? extends Block> type = resolve(value.getString("type"),
|
Class<? extends Block> type = resolve(value.getString("type"),
|
||||||
"io.anuke.mindustry.world",
|
"io.anuke.mindustry.world",
|
||||||
@@ -90,24 +132,25 @@ public class ContentParser{
|
|||||||
"io.anuke.mindustry.world.blocks.units"
|
"io.anuke.mindustry.world.blocks.units"
|
||||||
);
|
);
|
||||||
|
|
||||||
Block block = type.getDeclaredConstructor(String.class).newInstance(mod + "-" + name);
|
block = make(type, mod + "-" + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentContent = block;
|
||||||
read(() -> {
|
read(() -> {
|
||||||
if(value.has("consumes")){
|
if(value.has("consumes")){
|
||||||
for(JsonValue child : value.get("consumes")){
|
for(JsonValue child : value.get("consumes")){
|
||||||
if(child.name.equals("item")){
|
if(child.name.equals("item")){
|
||||||
if(child.isString()){
|
block.consumes.item(find(ContentType.item, child.asString()));
|
||||||
block.consumes.item(Vars.content.getByName(ContentType.item, child.asString()));
|
|
||||||
}else{
|
|
||||||
ItemStack stack = parser.readValue(ItemStack.class, child);
|
|
||||||
block.consumes.item(stack.item, stack.amount);
|
|
||||||
}
|
|
||||||
}else if(child.name.equals("items")){
|
}else if(child.name.equals("items")){
|
||||||
block.consumes.items(parser.readValue(ItemStack[].class, child));
|
block.consumes.add((Consume)parser.readValue(ConsumeItems.class, child));
|
||||||
}else if(child.name.equals("liquid")){
|
}else if(child.name.equals("liquid")){
|
||||||
LiquidStack stack = parser.readValue(LiquidStack.class, child);
|
block.consumes.add((Consume)parser.readValue(ConsumeLiquid.class, child));
|
||||||
block.consumes.liquid(stack.liquid, stack.amount);
|
|
||||||
}else if(child.name.equals("power")){
|
}else if(child.name.equals("power")){
|
||||||
|
if(child.isDouble()){
|
||||||
block.consumes.power(child.asFloat());
|
block.consumes.power(child.asFloat());
|
||||||
|
}else{
|
||||||
|
block.consumes.add((Consume)parser.readValue(ConsumePower.class, child));
|
||||||
|
}
|
||||||
}else if(child.name.equals("powerBuffered")){
|
}else if(child.name.equals("powerBuffered")){
|
||||||
block.consumes.powerBuffered(child.asFloat());
|
block.consumes.powerBuffered(child.asFloat());
|
||||||
}else{
|
}else{
|
||||||
@@ -121,7 +164,7 @@ public class ContentParser{
|
|||||||
|
|
||||||
//add research tech node
|
//add research tech node
|
||||||
if(value.has("research")){
|
if(value.has("research")){
|
||||||
TechTree.create(Vars.content.getByName(ContentType.block, value.get("research").asString()), block);
|
TechTree.create(find(ContentType.block, value.get("research").asString()), block);
|
||||||
}
|
}
|
||||||
|
|
||||||
//make block visible
|
//make block visible
|
||||||
@@ -133,8 +176,11 @@ public class ContentParser{
|
|||||||
return block;
|
return block;
|
||||||
},
|
},
|
||||||
ContentType.unit, (TypeParser<UnitType>)(mod, name, value) -> {
|
ContentType.unit, (TypeParser<UnitType>)(mod, name, value) -> {
|
||||||
|
readBundle(ContentType.unit, name, value);
|
||||||
|
|
||||||
Class<BaseUnit> type = resolve(value.getString("type"), "io.anuke.mindustry.entities.type.base");
|
Class<BaseUnit> type = resolve(value.getString("type"), "io.anuke.mindustry.entities.type.base");
|
||||||
UnitType unit = new UnitType(mod + "-" + name, supply(type));
|
UnitType unit = new UnitType(mod + "-" + name, supply(type));
|
||||||
|
currentContent = unit;
|
||||||
read(() -> readFields(unit, value, true));
|
read(() -> readFields(unit, value, true));
|
||||||
|
|
||||||
return unit;
|
return unit;
|
||||||
@@ -145,24 +191,57 @@ public class ContentParser{
|
|||||||
ContentType.zone, parser(ContentType.zone, Zone::new)
|
ContentType.zone, parser(ContentType.zone, Zone::new)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private <T extends Content> T find(ContentType type, String name){
|
||||||
|
Content c = Vars.content.getByName(type, name);
|
||||||
|
if(c == null) c = Vars.content.getByName(type, currentMod.name + "-" + name);
|
||||||
|
if(c == null) throw new IllegalArgumentException("No " + type + " found with name '" + name + "'");
|
||||||
|
return (T)c;
|
||||||
|
}
|
||||||
|
|
||||||
private <T extends Content> TypeParser<T> parser(ContentType type, Function<String, T> constructor){
|
private <T extends Content> TypeParser<T> parser(ContentType type, Function<String, T> constructor){
|
||||||
return (mod, name, value) -> {
|
return (mod, name, value) -> {
|
||||||
T item;
|
T item;
|
||||||
if(Vars.content.getByName(type, name) != null){
|
if(Vars.content.getByName(type, name) != null){
|
||||||
item = (T)Vars.content.getByName(type, name);
|
item = (T)Vars.content.getByName(type, name);
|
||||||
|
readBundle(type, name, value);
|
||||||
}else{
|
}else{
|
||||||
|
readBundle(type, name, value);
|
||||||
item = constructor.get(mod + "-" + name);
|
item = constructor.get(mod + "-" + name);
|
||||||
}
|
}
|
||||||
|
currentContent = item;
|
||||||
read(() -> readFields(item, value));
|
read(() -> readFields(item, value));
|
||||||
return item;
|
return item;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readBundle(ContentType type, String name, JsonValue value){
|
||||||
|
UnlockableContent cont = Vars.content.getByName(type, name) instanceof UnlockableContent ?
|
||||||
|
Vars.content.getByName(type, name) : null;
|
||||||
|
|
||||||
|
String entryName = cont == null ? type + "." + currentMod.name + "-" + name + "." : type + "." + cont.name + ".";
|
||||||
|
I18NBundle bundle = Core.bundle;
|
||||||
|
while(bundle.getParent() != null) bundle = bundle.getParent();
|
||||||
|
|
||||||
|
if(value.has("name")){
|
||||||
|
bundle.getProperties().put(entryName + "name", value.getString("name"));
|
||||||
|
if(cont != null) cont.localizedName = value.getString("name");
|
||||||
|
value.remove("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(value.has("description")){
|
||||||
|
bundle.getProperties().put(entryName + "description", value.getString("description"));
|
||||||
|
if(cont != null) cont.description = value.getString("description");
|
||||||
|
value.remove("description");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Call to read a content's extra info later.*/
|
/** Call to read a content's extra info later.*/
|
||||||
private void read(Runnable run){
|
private void read(Runnable run){
|
||||||
|
Content cont = currentContent;
|
||||||
LoadedMod mod = currentMod;
|
LoadedMod mod = currentMod;
|
||||||
reads.add(() -> {
|
reads.add(() -> {
|
||||||
this.currentMod = mod;
|
this.currentMod = mod;
|
||||||
|
this.currentContent = cont;
|
||||||
run.run();
|
run.run();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -173,7 +252,7 @@ public class ContentParser{
|
|||||||
if(!arr.isEmpty()){
|
if(!arr.isEmpty()){
|
||||||
Class<?> c = arr.first().getClass();
|
Class<?> c = arr.first().getClass();
|
||||||
//get base content class, skipping intermediates
|
//get base content class, skipping intermediates
|
||||||
while(!(c.getSuperclass() == Content.class || c.getSuperclass() == UnlockableContent.class || c.getSuperclass() == UnlockableContent.class)){
|
while(!(c.getSuperclass() == Content.class || c.getSuperclass() == UnlockableContent.class || Modifier.isAbstract(c.getSuperclass().getModifiers()))){
|
||||||
c = c.getSuperclass();
|
c = c.getSuperclass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +262,11 @@ public class ContentParser{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void finishParsing(){
|
public void finishParsing(){
|
||||||
|
try{
|
||||||
reads.each(Runnable::run);
|
reads.each(Runnable::run);
|
||||||
|
}catch(Exception e){
|
||||||
|
Vars.mods.handleError(new ModLoadException("Error occurred parsing content: " + currentContent, currentContent, e), currentMod);
|
||||||
|
}
|
||||||
reads.clear();
|
reads.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,9 +275,10 @@ public class ContentParser{
|
|||||||
* @param name the name of the file without its extension
|
* @param name the name of the file without its extension
|
||||||
* @param json the json to parse
|
* @param json the json to parse
|
||||||
* @param type the type of content this is
|
* @param type the type of content this is
|
||||||
|
* @param file file that this content is being parsed from
|
||||||
* @return the content that was parsed
|
* @return the content that was parsed
|
||||||
*/
|
*/
|
||||||
public Content parse(LoadedMod mod, String name, String json, ContentType type) throws Exception{
|
public Content parse(LoadedMod mod, String name, String json, FileHandle file, ContentType type) throws Exception{
|
||||||
if(contentTypes.isEmpty()){
|
if(contentTypes.isEmpty()){
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@@ -205,12 +289,36 @@ public class ContentParser{
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentMod = mod;
|
currentMod = mod;
|
||||||
|
boolean exists = Vars.content.getByName(type, name) != null;
|
||||||
Content c = parsers.get(type).parse(mod.name, name, value);
|
Content c = parsers.get(type).parse(mod.name, name, value);
|
||||||
|
if(!exists){
|
||||||
|
c.sourceFile = file;
|
||||||
c.mod = mod;
|
c.mod = mod;
|
||||||
|
}
|
||||||
checkNulls(c);
|
checkNulls(c);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> T make(Class<T> type){
|
||||||
|
try{
|
||||||
|
java.lang.reflect.Constructor<T> cons = type.getDeclaredConstructor();
|
||||||
|
cons.setAccessible(true);
|
||||||
|
return cons.newInstance();
|
||||||
|
}catch(Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T make(Class<T> type, String name){
|
||||||
|
try{
|
||||||
|
java.lang.reflect.Constructor<T> cons = type.getDeclaredConstructor(String.class);
|
||||||
|
cons.setAccessible(true);
|
||||||
|
return cons.newInstance(name);
|
||||||
|
}catch(Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private <T> Supplier<T> supply(Class<T> type){
|
private <T> Supplier<T> supply(Class<T> type){
|
||||||
try{
|
try{
|
||||||
java.lang.reflect.Constructor<T> cons = type.getDeclaredConstructor();
|
java.lang.reflect.Constructor<T> cons = type.getDeclaredConstructor();
|
||||||
@@ -260,13 +368,13 @@ public class ContentParser{
|
|||||||
private void checkNulls(Object object, ObjectSet<Object> checked){
|
private void checkNulls(Object object, ObjectSet<Object> checked){
|
||||||
checked.add(object);
|
checked.add(object);
|
||||||
|
|
||||||
parser.getFields(object.getClass()).each((name, field) -> {
|
parser.getFields(object.getClass()).values().toArray().each(field -> {
|
||||||
try{
|
try{
|
||||||
if(field.field.getType().isPrimitive()) return;
|
if(field.field.getType().isPrimitive()) return;
|
||||||
|
|
||||||
Object obj = field.field.get(object);
|
Object obj = field.field.get(object);
|
||||||
if(field.field.isAnnotationPresent(NonNull.class) && field.field.get(object) == null){
|
if(field.field.isAnnotationPresent(NonNull.class) && field.field.get(object) == null){
|
||||||
throw new RuntimeException("Field '" + name + "' in " + object.getClass().getSimpleName() + " is missing!");
|
throw new RuntimeException("Field '" + field.field.getName() + "' in " + object.getClass().getSimpleName() + " is missing!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(obj != null && !checked.contains(obj)){
|
if(obj != null && !checked.contains(obj)){
|
||||||
@@ -303,7 +411,7 @@ public class ContentParser{
|
|||||||
}
|
}
|
||||||
Field field = metadata.field;
|
Field field = metadata.field;
|
||||||
try{
|
try{
|
||||||
field.set(object, parser.readValue(field.getType(), metadata.elementType, child));
|
field.set(object, parser.readValue(field.getType(), metadata.elementType, child, metadata.keyType));
|
||||||
}catch(ReflectionException ex){
|
}catch(ReflectionException ex){
|
||||||
throw new SerializationException("Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
|
throw new SerializationException("Error accessing field: " + field.getName() + " (" + type.getName() + ")", ex);
|
||||||
}catch(SerializationException ex){
|
}catch(SerializationException ex){
|
||||||
@@ -319,18 +427,24 @@ public class ContentParser{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Tries to resolve a class from a list of potential class names. */
|
/** Tries to resolve a class from a list of potential class names. */
|
||||||
private <T> Class<T> resolve(String base, String... potentials) throws Exception{
|
private <T> Class<T> resolve(String base, String... potentials){
|
||||||
|
if(!base.isEmpty() && Character.isLowerCase(base.charAt(0))) base = Strings.capitalize(base);
|
||||||
|
|
||||||
for(String type : potentials){
|
for(String type : potentials){
|
||||||
try{
|
try{
|
||||||
return (Class<T>)Class.forName(type + '.' + base);
|
return (Class<T>)Class.forName(type + '.' + base);
|
||||||
}catch(Exception ignored){
|
}catch(Exception ignored){
|
||||||
|
try{
|
||||||
|
return (Class<T>)Class.forName(type + '$' + base);
|
||||||
|
}catch(Exception ignored2){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Type not found: " + potentials[0]);
|
}
|
||||||
|
throw new IllegalArgumentException("Types not found: " + base + "." + potentials[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface FieldParser{
|
private interface FieldParser{
|
||||||
Object parse(Class<?> type, JsonValue value);
|
Object parse(Class<?> type, JsonValue value) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface TypeParser<T extends Content>{
|
private interface TypeParser<T extends Content>{
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ public class Mods implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @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
|
public @Nullable LoadedMod getMod(Class<? extends Mod> type){
|
||||||
LoadedMod getMod(Class<? extends Mod> type){
|
|
||||||
return loaded.find(l -> l.mod.getClass() == type);
|
return loaded.find(l -> l.mod.getClass() == type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +60,7 @@ public class Mods implements Loadable{
|
|||||||
|
|
||||||
file.copyTo(dest);
|
file.copyTo(dest);
|
||||||
try{
|
try{
|
||||||
loaded.add(loadMod(file));
|
loaded.add(loadMod(file, false));
|
||||||
requiresReload = true;
|
requiresReload = true;
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
dest.delete();
|
dest.delete();
|
||||||
@@ -76,6 +75,7 @@ public class Mods implements Loadable{
|
|||||||
@Override
|
@Override
|
||||||
public void loadAsync(){
|
public void loadAsync(){
|
||||||
if(loaded.isEmpty()) return;
|
if(loaded.isEmpty()) return;
|
||||||
|
Time.mark();
|
||||||
|
|
||||||
packer = new PixmapPacker(2048, 2048, Format.RGBA8888, 2, true);
|
packer = new PixmapPacker(2048, 2048, Format.RGBA8888, 2, true);
|
||||||
|
|
||||||
@@ -104,11 +104,14 @@ public class Mods implements Loadable{
|
|||||||
});
|
});
|
||||||
Log.info("Packed {0} images for mod '{1}'.", packed[0], mod.meta.name);
|
Log.info("Packed {0} images for mod '{1}'.", packed[0], mod.meta.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.info("Time to pack textures: {0}", Time.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadSync(){
|
public void loadSync(){
|
||||||
if(packer == null) return;
|
if(packer == null) return;
|
||||||
|
Time.mark();
|
||||||
|
|
||||||
Texture editor = Core.atlas.find("clear-editor").getTexture();
|
Texture editor = Core.atlas.find("clear-editor").getTexture();
|
||||||
PixmapPacker editorPacker = new PixmapPacker(2048, 2048, Format.RGBA8888, 2, true);
|
PixmapPacker editorPacker = new PixmapPacker(2048, 2048, Format.RGBA8888, 2, true);
|
||||||
@@ -140,6 +143,7 @@ public class Mods implements Loadable{
|
|||||||
|
|
||||||
packer.dispose();
|
packer.dispose();
|
||||||
packer = null;
|
packer = null;
|
||||||
|
Log.info("Time to update textures: {0}", Time.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes a mod file and marks it for requiring a restart. */
|
/** Removes a mod file and marks it for requiring a restart. */
|
||||||
@@ -163,16 +167,30 @@ public class Mods implements Loadable{
|
|||||||
if(!file.extension().equals("jar") && !file.extension().equals("zip") && !(file.isDirectory() && file.child("mod.json").exists())) continue;
|
if(!file.extension().equals("jar") && !file.extension().equals("zip") && !(file.isDirectory() && file.child("mod.json").exists())) continue;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
LoadedMod mod = loadMod(file);
|
LoadedMod mod = loadMod(file, false);
|
||||||
if(mod.enabled()){
|
if(mod.enabled()){
|
||||||
loaded.add(mod);
|
loaded.add(mod);
|
||||||
}else{
|
}else{
|
||||||
disabled.add(mod);
|
disabled.add(mod);
|
||||||
}
|
}
|
||||||
}catch(IllegalArgumentException ignored){
|
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
Log.err("Failed to load plugin file {0}. Skipping.", file);
|
Log.err("Failed to load mod file {0}. Skipping.", file);
|
||||||
e.printStackTrace();
|
Log.err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//load workshop mods now
|
||||||
|
for(FileHandle file : platform.getExternalMods()){
|
||||||
|
try{
|
||||||
|
LoadedMod mod = loadMod(file, true);
|
||||||
|
if(mod.enabled()){
|
||||||
|
loaded.add(mod);
|
||||||
|
}else{
|
||||||
|
disabled.add(mod);
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.err("Failed to load mod workshop file {0}. Skipping.", file);
|
||||||
|
Log.err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,11 +202,14 @@ public class Mods implements Loadable{
|
|||||||
|
|
||||||
private void buildFiles(){
|
private void buildFiles(){
|
||||||
for(LoadedMod mod : loaded){
|
for(LoadedMod mod : loaded){
|
||||||
|
boolean zipFolder = !mod.file.isDirectory() && mod.root.parent() != null;
|
||||||
|
String parentName = zipFolder ? mod.root.name() : null;
|
||||||
for(FileHandle file : mod.root.list()){
|
for(FileHandle file : mod.root.list()){
|
||||||
//ignore special folders like bundles or sprites
|
//ignore special folders like bundles or sprites
|
||||||
if(file.isDirectory() && !specialFolders.contains(file.name())){
|
if(file.isDirectory() && !specialFolders.contains(file.name())){
|
||||||
//TODO calling child/parent on these files will give you gibberish; create wrapper class.
|
//TODO calling child/parent on these files will give you gibberish; create wrapper class.
|
||||||
file.walk(f -> tree.addFile(mod.file.isDirectory() ? f.path().substring(1 + mod.file.path().length()) : f.path(), f));
|
file.walk(f -> tree.addFile(mod.file.isDirectory() ? f.path().substring(1 + mod.file.path().length()) :
|
||||||
|
zipFolder ? f.path().substring(parentName.length() + 1) : f.path(), f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,6 +268,7 @@ public class Mods implements Loadable{
|
|||||||
/** Creates all the content found in mod files. */
|
/** Creates all the content found in mod files. */
|
||||||
public void loadContent(){
|
public void loadContent(){
|
||||||
for(LoadedMod mod : loaded){
|
for(LoadedMod mod : loaded){
|
||||||
|
safeRun(mod, () -> {
|
||||||
if(mod.root.child("content").exists()){
|
if(mod.root.child("content").exists()){
|
||||||
FileHandle contentRoot = mod.root.child("content");
|
FileHandle contentRoot = mod.root.child("content");
|
||||||
for(ContentType type : ContentType.all){
|
for(ContentType type : ContentType.all){
|
||||||
@@ -256,8 +278,9 @@ public class Mods implements Loadable{
|
|||||||
if(file.extension().equals("json")){
|
if(file.extension().equals("json")){
|
||||||
try{
|
try{
|
||||||
//this binds the content but does not load it entirely
|
//this binds the content but does not load it entirely
|
||||||
Content loaded = parser.parse(mod, file.nameWithoutExtension(), file.readString(), type);
|
Content loaded = parser.parse(mod, file.nameWithoutExtension(), file.readString("UTF-8"), file, type);
|
||||||
Log.info("[{0}] Loaded '{1}'.", mod.meta.name, loaded);
|
Log.info("[{0}] Loaded '{1}'.", mod.meta.name,
|
||||||
|
(loaded instanceof UnlockableContent ? ((UnlockableContent)loaded).localizedName : loaded));
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
throw new RuntimeException("Failed to parse content file '" + file + "' for mod '" + mod.meta.name + "'.", e);
|
throw new RuntimeException("Failed to parse content file '" + file + "' for mod '" + mod.meta.name + "'.", e);
|
||||||
}
|
}
|
||||||
@@ -266,11 +289,13 @@ public class Mods implements Loadable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//this finishes parsing content fields
|
//this finishes parsing content fields
|
||||||
parser.finishParsing();
|
parser.finishParsing();
|
||||||
|
|
||||||
|
//load content for code mods
|
||||||
each(Mod::loadContent);
|
each(Mod::loadContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,13 +349,49 @@ public class Mods implements Loadable{
|
|||||||
|
|
||||||
/** Iterates through each mod with a main class.*/
|
/** Iterates through each mod with a main class.*/
|
||||||
public void each(Consumer<Mod> cons){
|
public void each(Consumer<Mod> cons){
|
||||||
loaded.each(p -> p.mod != null, p -> cons.accept(p.mod));
|
loaded.each(p -> p.mod != null, p -> safeRun(p, () -> cons.accept(p.mod)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleError(Throwable t, LoadedMod mod){
|
||||||
|
Array<Throwable> causes = Strings.getCauses(t);
|
||||||
|
Content content = null;
|
||||||
|
for(Throwable e : causes){
|
||||||
|
if(e instanceof ModLoadException && ((ModLoadException) e).content != null){
|
||||||
|
content = ((ModLoadException) e).content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String realCause = "<???>";
|
||||||
|
for(int i = causes.size -1 ; i >= 0; i--){
|
||||||
|
if(causes.get(i).getMessage() != null){
|
||||||
|
realCause = causes.get(i).getMessage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(content != null){
|
||||||
|
throw new ModLoadException(Strings.format("Error loading '{0}' from mod '{1}' ({2}):\n{3}",
|
||||||
|
content, mod.meta.name, content.sourceFile.name(), realCause), content, t);
|
||||||
|
}else{
|
||||||
|
throw new ModLoadException("Error loading mod " + mod.meta.name, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void safeRun(LoadedMod mod, Runnable run){
|
||||||
|
try{
|
||||||
|
run.run();
|
||||||
|
}catch(Throwable t){
|
||||||
|
handleError(t, mod);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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(FileHandle sourceFile) throws Exception{
|
private LoadedMod loadMod(FileHandle sourceFile, boolean workshop) throws Exception{
|
||||||
FileHandle zip = sourceFile.isDirectory() ? sourceFile : new ZipFileHandle(sourceFile);
|
FileHandle zip = sourceFile.isDirectory() ? sourceFile : new ZipFileHandle(sourceFile);
|
||||||
|
if(zip.list().length == 1 && zip.list()[0].isDirectory()){
|
||||||
|
zip = zip.list()[0];
|
||||||
|
}
|
||||||
|
|
||||||
FileHandle metaf = zip.child("mod.json").exists() ? zip.child("mod.json") : zip.child("plugin.json");
|
FileHandle metaf = zip.child("mod.json").exists() ? zip.child("mod.json") : zip.child("plugin.json");
|
||||||
if(!metaf.exists()){
|
if(!metaf.exists()){
|
||||||
@@ -341,6 +402,12 @@ public class Mods implements Loadable{
|
|||||||
ModMeta meta = json.fromJson(ModMeta.class, metaf.readString());
|
ModMeta meta = json.fromJson(ModMeta.class, metaf.readString());
|
||||||
String camelized = meta.name.replace(" ", "");
|
String camelized = meta.name.replace(" ", "");
|
||||||
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(" ", "-");
|
||||||
|
|
||||||
|
if(loaded.contains(m -> m.name.equals(baseName)) || disabled.contains(m -> m.name.equals(baseName))){
|
||||||
|
throw new IllegalArgumentException("A mod with the name '" + baseName + "' is already imported.");
|
||||||
|
}
|
||||||
|
|
||||||
Mod mainMod;
|
Mod mainMod;
|
||||||
|
|
||||||
FileHandle mainFile = zip;
|
FileHandle mainFile = zip;
|
||||||
@@ -386,6 +453,8 @@ public class Mods implements Loadable{
|
|||||||
public final String name;
|
public final String name;
|
||||||
/** This mod's metadata. */
|
/** This mod's metadata. */
|
||||||
public final ModMeta meta;
|
public final ModMeta meta;
|
||||||
|
/** The ID of this mod in the workshop.*/
|
||||||
|
public @Nullable String workshopID;
|
||||||
|
|
||||||
public LoadedMod(FileHandle file, FileHandle root, Mod mod, ModMeta meta){
|
public LoadedMod(FileHandle file, FileHandle root, Mod mod, ModMeta meta){
|
||||||
this.root = root;
|
this.root = root;
|
||||||
@@ -398,6 +467,15 @@ public class Mods implements Loadable{
|
|||||||
public boolean enabled(){
|
public boolean enabled(){
|
||||||
return Core.settings.getBool(name + "-enabled", true);
|
return Core.settings.getBool(name + "-enabled", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "LoadedMod{" +
|
||||||
|
"file=" + file +
|
||||||
|
", root=" + root +
|
||||||
|
", name='" + name + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Plugin metadata information.*/
|
/** Plugin metadata information.*/
|
||||||
@@ -407,4 +485,22 @@ public class Mods implements Loadable{
|
|||||||
/** 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Thrown when an error occurs while loading a mod.*/
|
||||||
|
public static class ModLoadException extends RuntimeException{
|
||||||
|
public Content content;
|
||||||
|
public LoadedMod mod;
|
||||||
|
|
||||||
|
public ModLoadException(String message, Throwable cause){
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModLoadException(String message, @Nullable Content content, Throwable cause){
|
||||||
|
super(message, cause);
|
||||||
|
this.content = content;
|
||||||
|
if(content != null){
|
||||||
|
this.mod = content.mod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import io.anuke.mindustry.world.blocks.*;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.content;
|
import static io.anuke.mindustry.Vars.content;
|
||||||
|
|
||||||
public class Item extends UnlockableContent implements Comparable<Item>{
|
public class Item extends UnlockableContent{
|
||||||
public final Color color;
|
public final Color color;
|
||||||
|
|
||||||
/** type of the item; used for tabs and core acceptance. default value is {@link ItemType#resource}. */
|
/** type of the item; used for tabs and core acceptance. default value is {@link ItemType#resource}. */
|
||||||
@@ -61,11 +61,6 @@ public class Item extends UnlockableContent implements Comparable<Item>{
|
|||||||
return localizedName();
|
return localizedName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(Item item){
|
|
||||||
return Integer.compare(id, item.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ContentType getContentType(){
|
public ContentType getContentType(){
|
||||||
return ContentType.item;
|
return ContentType.item;
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ public class ItemStack implements Comparable<ItemStack>{
|
|||||||
item = Items.copper;
|
item = Items.copper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ItemStack copy(){
|
||||||
|
return new ItemStack(item, amount);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean equals(ItemStack other){
|
public boolean equals(ItemStack other){
|
||||||
return other != null && other.item == item && other.amount == amount;
|
return other != null && other.item == item && other.amount == amount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,34 +5,32 @@ import io.anuke.arc.collection.*;
|
|||||||
import io.anuke.arc.function.*;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.scene.ui.layout.*;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.arc.util.*;
|
|
||||||
import io.anuke.arc.util.ArcAnnotate.*;
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
|
import io.anuke.mindustry.game.Objectives.*;
|
||||||
import io.anuke.mindustry.maps.generators.*;
|
import io.anuke.mindustry.maps.generators.*;
|
||||||
import io.anuke.mindustry.world.*;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class Zone extends UnlockableContent{
|
public class Zone extends UnlockableContent{
|
||||||
public @NonNull Generator generator;
|
public @NonNull Generator generator;
|
||||||
public Block[] blockRequirements = {};
|
public @NonNull Objective configureObjective = new ZoneWave(this, 15);
|
||||||
public ZoneRequirement[] zoneRequirements = {};
|
public Array<Objective> requirements = new Array<>();
|
||||||
public Item[] resources = {};
|
//TODO autogenerate
|
||||||
|
public Array<Item> resources = new Array<>();
|
||||||
|
|
||||||
public Consumer<Rules> rules = rules -> {};
|
public Consumer<Rules> rules = rules -> {};
|
||||||
public boolean alwaysUnlocked;
|
public boolean alwaysUnlocked;
|
||||||
public int conditionWave = Integer.MAX_VALUE;
|
public int conditionWave = Integer.MAX_VALUE;
|
||||||
public int configureWave = 15;
|
|
||||||
public int launchPeriod = 10;
|
public int launchPeriod = 10;
|
||||||
public Loadout loadout = Loadouts.basicShard;
|
public Loadout loadout = Loadouts.basicShard;
|
||||||
public TextureRegion preview;
|
public TextureRegion preview;
|
||||||
|
|
||||||
protected ItemStack[] baseLaunchCost = {};
|
protected Array<ItemStack> baseLaunchCost = new Array<>();
|
||||||
protected Array<ItemStack> startingItems = new Array<>();
|
protected Array<ItemStack> startingItems = new Array<>();
|
||||||
protected ItemStack[] launchCost = null;
|
protected Array<ItemStack> launchCost;
|
||||||
|
|
||||||
private Array<ItemStack> defaultStartingItems = new Array<>();
|
private Array<ItemStack> defaultStartingItems = new Array<>();
|
||||||
|
|
||||||
@@ -47,7 +45,7 @@ public class Zone extends UnlockableContent{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
preview = Core.atlas.find("zone-" + name);
|
preview = Core.atlas.find("zone-" + name, Core.atlas.find(name + "-zone"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rules getRules(){
|
public Rules getRules(){
|
||||||
@@ -60,35 +58,15 @@ public class Zone extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBossWave(int wave){
|
|
||||||
return wave % configureWave == 0 && wave > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLaunchWave(int wave){
|
public boolean isLaunchWave(int wave){
|
||||||
return metCondition() && wave % launchPeriod == 0;
|
return metCondition() && wave % launchPeriod == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canUnlock(){
|
public boolean canUnlock(){
|
||||||
if(data.isUnlocked(this)){
|
return data.isUnlocked(this) || !requirements.contains(r -> !r.complete());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(ZoneRequirement other : zoneRequirements){
|
public Array<ItemStack> getLaunchCost(){
|
||||||
if(other.zone.bestWave() < other.wave){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Block other : blockRequirements){
|
|
||||||
if(!data.isUnlocked(other)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemStack[] getLaunchCost(){
|
|
||||||
if(launchCost == null){
|
if(launchCost == null){
|
||||||
updateLaunchCost();
|
updateLaunchCost();
|
||||||
}
|
}
|
||||||
@@ -104,30 +82,54 @@ public class Zone extends UnlockableContent{
|
|||||||
defaultStartingItems.each(stack -> startingItems.add(new ItemStack(stack.item, stack.amount)));
|
defaultStartingItems.each(stack -> startingItems.add(new ItemStack(stack.item, stack.amount)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasLaunched(){
|
||||||
|
return Core.settings.getBool(name + "-launched", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLaunched(){
|
||||||
|
updateObjectives(() -> {
|
||||||
|
Core.settings.put(name + "-launched", true);
|
||||||
|
data.modified();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void updateWave(int wave){
|
public void updateWave(int wave){
|
||||||
int value = Core.settings.getInt(name + "-wave", 0);
|
int value = Core.settings.getInt(name + "-wave", 0);
|
||||||
|
|
||||||
if(value < wave){
|
if(value < wave){
|
||||||
|
updateObjectives(() -> {
|
||||||
Core.settings.put(name + "-wave", wave);
|
Core.settings.put(name + "-wave", wave);
|
||||||
data.modified();
|
data.modified();
|
||||||
|
});
|
||||||
for(Zone zone : content.zones()){
|
|
||||||
ZoneRequirement req = Structs.find(zone.zoneRequirements, f -> f.zone == this);
|
|
||||||
if(req != null && wave == req.wave + 1){
|
|
||||||
Events.fire(new ZoneRequireCompleteEvent(zone, this));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(wave == configureWave + 1){
|
public void updateObjectives(Runnable closure){
|
||||||
|
Array<ZoneObjective> incomplete = content.zones()
|
||||||
|
.map(z -> z.requirements).<Objective>flatten()
|
||||||
|
.select(o -> o.zone() == this && !o.complete())
|
||||||
|
.as(ZoneObjective.class);
|
||||||
|
|
||||||
|
boolean wasConfig = configureObjective.complete();
|
||||||
|
|
||||||
|
closure.run();
|
||||||
|
for(ZoneObjective objective : incomplete){
|
||||||
|
if(objective.complete()){
|
||||||
|
Events.fire(new ZoneRequireCompleteEvent(objective.zone, content.zones().find(z -> z.requirements.contains(objective)), objective));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!wasConfig && configureObjective.complete()){
|
||||||
Events.fire(new ZoneConfigureCompleteEvent(this));
|
Events.fire(new ZoneConfigureCompleteEvent(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public int bestWave(){
|
public int bestWave(){
|
||||||
return Core.settings.getInt(name + "-wave", 0);
|
return Core.settings.getInt(name + "-wave", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCompleted(){
|
/** @return whether initial conditions to launch are met. */
|
||||||
|
public boolean isLaunchMet(){
|
||||||
return bestWave() >= conditionWave;
|
return bestWave() >= conditionWave;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +154,7 @@ public class Zone extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
stacks.sort();
|
stacks.sort();
|
||||||
launchCost = stacks.toArray(ItemStack.class);
|
launchCost = stacks;
|
||||||
Core.settings.putObject(name + "-starting-items", startingItems);
|
Core.settings.putObject(name + "-starting-items", startingItems);
|
||||||
data.modified();
|
data.modified();
|
||||||
}
|
}
|
||||||
@@ -164,13 +166,13 @@ public class Zone extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canConfigure(){
|
public boolean canConfigure(){
|
||||||
return bestWave() >= configureWave;
|
return configureObjective.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
generator.init(loadout);
|
generator.init(loadout);
|
||||||
Arrays.sort(resources);
|
resources.sort();
|
||||||
|
|
||||||
for(ItemStack stack : startingItems){
|
for(ItemStack stack : startingItems){
|
||||||
defaultStartingItems.add(new ItemStack(stack.item, stack.amount));
|
defaultStartingItems.add(new ItemStack(stack.item, stack.amount));
|
||||||
@@ -208,22 +210,4 @@ public class Zone extends UnlockableContent{
|
|||||||
return ContentType.zone;
|
return ContentType.zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ZoneRequirement{
|
|
||||||
public final Zone zone;
|
|
||||||
public final int wave;
|
|
||||||
|
|
||||||
public ZoneRequirement(Zone zone, int wave){
|
|
||||||
this.zone = zone;
|
|
||||||
this.wave = wave;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ZoneRequirement[] with(Object... objects){
|
|
||||||
ZoneRequirement[] out = new ZoneRequirement[objects.length / 2];
|
|
||||||
for(int i = 0; i < objects.length; i += 2){
|
|
||||||
out[i / 2] = new ZoneRequirement((Zone)objects[i], (Integer)objects[i + 1]);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,112 @@
|
|||||||
package io.anuke.mindustry.ui.dialogs;
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
|
import io.anuke.arc.*;
|
||||||
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.function.*;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.graphics.Color;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.scene.ui.layout.Table;
|
import io.anuke.arc.scene.style.*;
|
||||||
|
import io.anuke.arc.scene.ui.*;
|
||||||
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.*;
|
import io.anuke.mindustry.*;
|
||||||
import io.anuke.mindustry.content.Blocks;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.content.Items;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.game.Rules;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.Pal;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.type.ItemType;
|
import io.anuke.mindustry.ui.*;
|
||||||
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.tilesize;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class CustomRulesDialog extends FloatingDialog{
|
public class CustomRulesDialog extends FloatingDialog{
|
||||||
private Table main;
|
private Table main;
|
||||||
private Rules rules;
|
private Rules rules;
|
||||||
private Supplier<Rules> resetter;
|
private Supplier<Rules> resetter;
|
||||||
private LoadoutDialog loadoutDialog;
|
private LoadoutDialog loadoutDialog;
|
||||||
|
private FloatingDialog banDialog;
|
||||||
|
|
||||||
public CustomRulesDialog(){
|
public CustomRulesDialog(){
|
||||||
super("$mode.custom");
|
super("$mode.custom");
|
||||||
|
|
||||||
loadoutDialog = new LoadoutDialog();
|
loadoutDialog = new LoadoutDialog();
|
||||||
|
banDialog = new FloatingDialog("$bannedblocks");
|
||||||
|
banDialog.addCloseButton();
|
||||||
|
|
||||||
|
banDialog.shown(this::rebuildBanned);
|
||||||
|
banDialog.buttons.addImageTextButton("$addall", Icon.arrow16Small, () -> {
|
||||||
|
rules.bannedBlocks.addAll(content.blocks().select(Block::isBuildable));
|
||||||
|
rebuildBanned();
|
||||||
|
}).size(180, 64f);
|
||||||
|
|
||||||
|
banDialog.buttons.addImageTextButton("$clear", Icon.trash16Small, () -> {
|
||||||
|
rules.bannedBlocks.clear();
|
||||||
|
rebuildBanned();
|
||||||
|
}).size(180, 64f);
|
||||||
|
|
||||||
setFillParent(true);
|
setFillParent(true);
|
||||||
shown(this::setup);
|
shown(this::setup);
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void rebuildBanned(){
|
||||||
|
float previousScroll = banDialog.cont.getChildren().isEmpty() ? 0f : ((ScrollPane)banDialog.cont.getChildren().first()).getScrollY();
|
||||||
|
banDialog.cont.clear();
|
||||||
|
banDialog.cont.pane(t -> {
|
||||||
|
t.margin(10f);
|
||||||
|
|
||||||
|
if(rules.bannedBlocks.isEmpty()){
|
||||||
|
t.add("$empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<Block> array = Array.with(rules.bannedBlocks);
|
||||||
|
array.sort();
|
||||||
|
|
||||||
|
int cols = mobile && Core.graphics.isPortrait() ? 1 : mobile ? 2 : 3;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for(Block block : array){
|
||||||
|
t.table(Tex.underline, b -> {
|
||||||
|
b.left().margin(4f);
|
||||||
|
b.addImage(block.icon(Cicon.medium)).size(Cicon.medium.size).padRight(3);
|
||||||
|
b.add(block.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap();
|
||||||
|
|
||||||
|
b.addImageButton(Icon.cancelSmall, Styles.clearPartiali, () -> {
|
||||||
|
rules.bannedBlocks.remove(block);
|
||||||
|
rebuildBanned();
|
||||||
|
}).size(70f).pad(-4f).padLeft(0f);
|
||||||
|
}).size(300f, 70f).padRight(5);
|
||||||
|
|
||||||
|
if(++i % cols == 0){
|
||||||
|
t.row();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).get().setScrollYForce(previousScroll);
|
||||||
|
banDialog.cont.row();
|
||||||
|
banDialog.cont.addImageTextButton("$add", Icon.addSmall, () -> {
|
||||||
|
FloatingDialog dialog = new FloatingDialog("$add");
|
||||||
|
dialog.cont.pane(t -> {
|
||||||
|
t.left().margin(14f);
|
||||||
|
int[] i = {0};
|
||||||
|
content.blocks().each(b -> !rules.bannedBlocks.contains(b) && b.isBuildable(), b -> {
|
||||||
|
int cols = mobile && Core.graphics.isPortrait() ? 4 : 12;
|
||||||
|
t.addImageButton(new TextureRegionDrawable(b.icon(Cicon.medium)), Styles.cleari, () -> {
|
||||||
|
rules.bannedBlocks.add(b);
|
||||||
|
rebuildBanned();
|
||||||
|
dialog.hide();
|
||||||
|
}).size(60f).get().resizeImage(Cicon.medium.size);
|
||||||
|
|
||||||
|
if(++i[0] % cols == 0){
|
||||||
|
t.row();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.addCloseButton();
|
||||||
|
dialog.show();
|
||||||
|
}).size(300f, 64f);
|
||||||
|
}
|
||||||
|
|
||||||
public void show(Rules rules, Supplier<Rules> resetter){
|
public void show(Rules rules, Supplier<Rules> resetter){
|
||||||
this.rules = rules;
|
this.rules = rules;
|
||||||
this.resetter = resetter;
|
this.resetter = resetter;
|
||||||
@@ -67,18 +145,17 @@ public class CustomRulesDialog extends FloatingDialog{
|
|||||||
number("$rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier);
|
number("$rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier);
|
||||||
|
|
||||||
main.addButton("$configure",
|
main.addButton("$configure",
|
||||||
() -> loadoutDialog.show(
|
() -> loadoutDialog.show(Blocks.coreShard.itemCapacity, rules.loadout,
|
||||||
Blocks.coreShard.itemCapacity,
|
|
||||||
() -> rules.loadout,
|
|
||||||
() -> {
|
() -> {
|
||||||
rules.loadout.clear();
|
rules.loadout.clear();
|
||||||
rules.loadout.add(new ItemStack(Items.copper, 100));
|
rules.loadout.add(new ItemStack(Items.copper, 100));
|
||||||
},
|
}, () -> {}, () -> {}
|
||||||
() -> {}, () -> {},
|
|
||||||
item -> item.type == ItemType.material
|
|
||||||
)).left().width(300f);
|
)).left().width(300f);
|
||||||
main.row();
|
main.row();
|
||||||
|
|
||||||
|
main.addButton("$bannedblocks", banDialog::show).left().width(300f);
|
||||||
|
main.row();
|
||||||
|
|
||||||
title("$rules.title.player");
|
title("$rules.title.player");
|
||||||
number("$rules.playerdamagemultiplier", f -> rules.playerDamageMultiplier = f, () -> rules.playerDamageMultiplier);
|
number("$rules.playerdamagemultiplier", f -> rules.playerDamageMultiplier = f, () -> rules.playerDamageMultiplier);
|
||||||
number("$rules.playerhealthmultiplier", f -> rules.playerHealthMultiplier = f, () -> rules.playerHealthMultiplier);
|
number("$rules.playerhealthmultiplier", f -> rules.playerHealthMultiplier = f, () -> rules.playerHealthMultiplier);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package io.anuke.mindustry.ui.dialogs;
|
|||||||
|
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.collection.ObjectSet.*;
|
|
||||||
import io.anuke.arc.function.*;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
@@ -21,9 +20,7 @@ import io.anuke.mindustry.gen.*;
|
|||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.io.SaveIO.*;
|
import io.anuke.mindustry.io.SaveIO.*;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.type.Zone.*;
|
|
||||||
import io.anuke.mindustry.ui.*;
|
import io.anuke.mindustry.ui.*;
|
||||||
import io.anuke.mindustry.ui.Styles;
|
|
||||||
import io.anuke.mindustry.ui.TreeLayout.*;
|
import io.anuke.mindustry.ui.TreeLayout.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
@@ -129,7 +126,7 @@ public class DeployDialog extends FloatingDialog{
|
|||||||
|
|
||||||
button.defaults().colspan(2);
|
button.defaults().colspan(2);
|
||||||
button.row();
|
button.row();
|
||||||
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
|
button.add(Core.bundle.format("save", color + slot.getWave()));
|
||||||
button.row();
|
button.row();
|
||||||
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
|
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
|
||||||
button.row();
|
button.row();
|
||||||
@@ -155,8 +152,8 @@ public class DeployDialog extends FloatingDialog{
|
|||||||
for(ZoneNode node : nodes){
|
for(ZoneNode node : nodes){
|
||||||
node.allChildren.clear();
|
node.allChildren.clear();
|
||||||
node.allChildren.addAll(node.children);
|
node.allChildren.addAll(node.children);
|
||||||
for(ZoneNode other : new ObjectSetIterator<>(nodes)){
|
for(ZoneNode other : nodes){
|
||||||
if(Structs.contains(other.zone.zoneRequirements, req -> req.zone == node.zone)){
|
if(other.zone.requirements.contains(req -> req.zone() == node.zone)){
|
||||||
node.allChildren.add(other);
|
node.allChildren.add(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,12 +161,7 @@ public class DeployDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean hidden(Zone zone){
|
boolean hidden(Zone zone){
|
||||||
for(ZoneRequirement other : zone.zoneRequirements){
|
return zone.requirements.contains(o -> o.zone() != null && o.zone().locked());
|
||||||
if(!data.isUnlocked(other.zone)){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildButton(Zone zone, Button button){
|
void buildButton(Zone zone, Button button){
|
||||||
@@ -258,7 +250,7 @@ public class DeployDialog extends FloatingDialog{
|
|||||||
//this.height /= 2f;
|
//this.height /= 2f;
|
||||||
nodes.add(this);
|
nodes.add(this);
|
||||||
|
|
||||||
arr.selectFrom(content.zones(), other -> other.zoneRequirements.length > 0 && other.zoneRequirements[0].zone == zone);
|
arr.selectFrom(content.zones(), other -> other.requirements.size > 0 && other.requirements.first().zone() == zone);
|
||||||
|
|
||||||
children = new ZoneNode[arr.size];
|
children = new ZoneNode[arr.size];
|
||||||
for(int i = 0; i < children.length; i++){
|
for(int i = 0; i < children.length; i++){
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import io.anuke.arc.graphics.*;
|
|||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.*;
|
import io.anuke.mindustry.*;
|
||||||
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.ui.*;
|
import io.anuke.mindustry.ui.*;
|
||||||
|
|
||||||
@@ -69,13 +70,19 @@ public class HostDialog extends FloatingDialog{
|
|||||||
player.isAdmin = true;
|
player.isAdmin = true;
|
||||||
|
|
||||||
if(steam){
|
if(steam){
|
||||||
Core.app.post(() -> Core.settings.getBoolOnce("steampublic", () -> {
|
Core.app.post(() -> Core.settings.getBoolOnce("steampublic2", () -> {
|
||||||
ui.showCustomConfirm("$setting.publichost.name", "$public.confirm", "$yes", "$no", () -> {
|
ui.showCustomConfirm("$setting.publichost.name", "$public.confirm", "$yes", "$no", () -> {
|
||||||
Core.settings.putSave("publichost", true);
|
Core.settings.putSave("publichost", true);
|
||||||
platform.updateLobby();
|
platform.updateLobby();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Version.modifier.contains("beta")){
|
||||||
|
Core.settings.putSave("publichost", false);
|
||||||
|
platform.updateLobby();
|
||||||
|
Core.settings.getBoolOnce("betapublic", () -> ui.showInfo("$public.beta"));
|
||||||
|
}
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
ui.showException("$server.error", e);
|
ui.showException("$server.error", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package io.anuke.mindustry.ui.dialogs;
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.Core;
|
||||||
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.scene.ui.layout.Table;
|
import io.anuke.arc.scene.ui.layout.Table;
|
||||||
import io.anuke.arc.util.Log;
|
import io.anuke.arc.util.Log;
|
||||||
@@ -14,6 +15,10 @@ import static io.anuke.mindustry.Vars.ui;
|
|||||||
|
|
||||||
public class LanguageDialog extends FloatingDialog{
|
public class LanguageDialog extends FloatingDialog{
|
||||||
private Locale lastLocale;
|
private Locale lastLocale;
|
||||||
|
private ObjectMap<Locale, String> displayNames = ObjectMap.of(
|
||||||
|
Locale.TRADITIONAL_CHINESE, "正體中文",
|
||||||
|
Locale.SIMPLIFIED_CHINESE, "简体中文"
|
||||||
|
);
|
||||||
|
|
||||||
public LanguageDialog(){
|
public LanguageDialog(){
|
||||||
super("$settings.language");
|
super("$settings.language");
|
||||||
@@ -30,7 +35,7 @@ public class LanguageDialog extends FloatingDialog{
|
|||||||
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
||||||
|
|
||||||
for(Locale loc : locales){
|
for(Locale loc : locales){
|
||||||
TextButton button = new TextButton(Strings.capitalize(loc.getDisplayName(loc)), Styles.clearTogglet);
|
TextButton button = new TextButton(Strings.capitalize(displayNames.get(loc, loc.getDisplayName(loc))), Styles.clearTogglet);
|
||||||
button.clicked(() -> {
|
button.clicked(() -> {
|
||||||
if(getLocale().equals(loc)) return;
|
if(getLocale().equals(loc)) return;
|
||||||
Core.settings.put("locale", loc.toString());
|
Core.settings.put("locale", loc.toString());
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ package io.anuke.mindustry.ui.dialogs;
|
|||||||
|
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.function.*;
|
|
||||||
import io.anuke.arc.input.*;
|
import io.anuke.arc.input.*;
|
||||||
import io.anuke.arc.scene.ui.*;
|
|
||||||
import io.anuke.arc.scene.ui.layout.*;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
@@ -16,10 +14,12 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
|
|
||||||
public class LoadoutDialog extends FloatingDialog{
|
public class LoadoutDialog extends FloatingDialog{
|
||||||
private Runnable hider;
|
private Runnable hider;
|
||||||
private Supplier<Array<ItemStack>> supplier;
|
//private Supplier<Array<ItemStack>> supplier;
|
||||||
private Runnable resetter;
|
private Runnable resetter;
|
||||||
private Runnable updater;
|
private Runnable updater;
|
||||||
private Predicate<Item> filter;
|
private Array<ItemStack> stacks = new Array<>();
|
||||||
|
private Array<ItemStack> originalStacks = new Array<>();
|
||||||
|
//private Predicate<Item> filter;
|
||||||
private Table items;
|
private Table items;
|
||||||
private int capacity;
|
private int capacity;
|
||||||
|
|
||||||
@@ -33,54 +33,37 @@ public class LoadoutDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cont.add(items = new Table()).left();
|
cont.pane(t -> items = t.margin(10f)).left();
|
||||||
|
|
||||||
shown(this::setup);
|
shown(this::setup);
|
||||||
hidden(() -> {
|
hidden(() -> {
|
||||||
|
originalStacks.selectFrom(stacks, s -> s.amount > 0);
|
||||||
|
updater.run();
|
||||||
if(hider != null){
|
if(hider != null){
|
||||||
hider.run();
|
hider.run();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cont.row();
|
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
|
||||||
|
|
||||||
cont.addButton("$add", () -> {
|
buttons.addImageTextButton("$settings.reset", Icon.refreshSmall, () -> {
|
||||||
FloatingDialog dialog = new FloatingDialog("");
|
|
||||||
dialog.setFillParent(false);
|
|
||||||
for(Item item : content.items().select(item -> filter.test(item) && item.type == ItemType.material && supplier.get().find(stack -> stack.item == item) == null)){
|
|
||||||
TextButton button = dialog.cont.addButton("", Styles.cleart, () -> {
|
|
||||||
dialog.hide();
|
|
||||||
supplier.get().add(new ItemStack(item, 0));
|
|
||||||
updater.run();
|
|
||||||
setup();
|
|
||||||
}).size(300f, 36f).get();
|
|
||||||
button.clearChildren();
|
|
||||||
button.left();
|
|
||||||
button.addImage(item.icon(Cicon.small)).size(8 * 3).pad(4);
|
|
||||||
button.add(item.localizedName);
|
|
||||||
dialog.cont.row();
|
|
||||||
}
|
|
||||||
dialog.show();
|
|
||||||
}).size(100f, 40).left().disabled(b -> !content.items().contains(item -> filter.test(item) && !supplier.get().contains(stack -> stack.item == item)));
|
|
||||||
|
|
||||||
cont.row();
|
|
||||||
cont.addButton("$settings.reset", () -> {
|
|
||||||
resetter.run();
|
resetter.run();
|
||||||
updater.run();
|
updater.run();
|
||||||
setup();
|
setup();
|
||||||
}).size(210f, 64f);
|
}).size(210f, 64f);
|
||||||
|
|
||||||
cont.row();
|
|
||||||
cont.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void show(int capacity, Supplier<Array<ItemStack>> supplier, Runnable reseter, Runnable updater, Runnable hider, Predicate<Item> filter){
|
public void show(int capacity, Array<ItemStack> stacks, Runnable reseter, Runnable updater, Runnable hider){
|
||||||
|
this.originalStacks = stacks;
|
||||||
|
this.stacks = stacks.map(ItemStack::copy);
|
||||||
|
this.stacks.addAll(content.items().select(i -> i.type == ItemType.material &&
|
||||||
|
!stacks.contains(stack -> stack.item == i)).map(i -> new ItemStack(i, 0)));
|
||||||
|
this.stacks.sort(Structs.comparingInt(s -> s.item.id));
|
||||||
this.resetter = reseter;
|
this.resetter = reseter;
|
||||||
this.supplier = supplier;
|
|
||||||
this.updater = updater;
|
this.updater = updater;
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
this.hider = hider;
|
this.hider = hider;
|
||||||
this.filter = filter;
|
//this.filter = filter;
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,26 +71,23 @@ public class LoadoutDialog extends FloatingDialog{
|
|||||||
items.clearChildren();
|
items.clearChildren();
|
||||||
items.left();
|
items.left();
|
||||||
float bsize = 40f;
|
float bsize = 40f;
|
||||||
int step = 50;
|
|
||||||
|
|
||||||
for(ItemStack stack : supplier.get()){
|
int i = 0;
|
||||||
items.addButton("x", Styles.clearPartialt, () -> {
|
|
||||||
supplier.get().remove(stack);
|
|
||||||
updater.run();
|
|
||||||
setup();
|
|
||||||
}).size(bsize);
|
|
||||||
|
|
||||||
items.addButton("-", Styles.clearPartialt, () -> {
|
for(ItemStack stack : stacks){
|
||||||
stack.amount = Math.max(stack.amount - step, 0);
|
items.table(Tex.pane, t -> {
|
||||||
|
t.margin(4).marginRight(8).left();
|
||||||
|
t.addButton("-", Styles.cleart, () -> {
|
||||||
|
stack.amount = Math.max(stack.amount - step(stack.amount), 0);
|
||||||
updater.run();
|
updater.run();
|
||||||
}).size(bsize);
|
}).size(bsize);
|
||||||
|
|
||||||
items.addButton("+", Styles.clearPartialt, () -> {
|
t.addButton("+", Styles.cleart, () -> {
|
||||||
stack.amount = Math.min(stack.amount + step, capacity);
|
stack.amount = Math.min(stack.amount + step(stack.amount), capacity);
|
||||||
updater.run();
|
updater.run();
|
||||||
}).size(bsize);
|
}).size(bsize);
|
||||||
|
|
||||||
items.addImageButton(Icon.pencilSmaller, Styles.clearPartial2i, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
|
t.addImageButton(Icon.pencilSmaller, Styles.cleari, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
|
||||||
if(Strings.canParsePostiveInt(str)){
|
if(Strings.canParsePostiveInt(str)){
|
||||||
int amount = Strings.parseInt(str);
|
int amount = Strings.parseInt(str);
|
||||||
if(amount >= 0 && amount <= capacity){
|
if(amount >= 0 && amount <= capacity){
|
||||||
@@ -119,10 +99,26 @@ public class LoadoutDialog extends FloatingDialog{
|
|||||||
ui.showInfo(Core.bundle.format("configure.invalid", capacity));
|
ui.showInfo(Core.bundle.format("configure.invalid", capacity));
|
||||||
})).size(bsize);
|
})).size(bsize);
|
||||||
|
|
||||||
items.addImage(stack.item.icon(Cicon.small)).size(8 * 3).padRight(4).padLeft(4);
|
t.addImage(stack.item.icon(Cicon.small)).size(8 * 3).padRight(4).padLeft(4);
|
||||||
items.label(() -> stack.amount + "").left();
|
t.label(() -> stack.amount + "").left().width(90f);
|
||||||
|
}).pad(2).left().fillX();
|
||||||
|
|
||||||
|
|
||||||
|
if(++i % 2 == 0 || (mobile && Core.graphics.isPortrait())){
|
||||||
items.row();
|
items.row();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int step(int amount){
|
||||||
|
if(amount < 1000){
|
||||||
|
return 100;
|
||||||
|
}else if(amount < 2000){
|
||||||
|
return 200;
|
||||||
|
}else if(amount < 5000){
|
||||||
|
return 500;
|
||||||
|
}else{
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package io.anuke.mindustry.ui.dialogs;
|
|||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
|
import io.anuke.arc.util.io.*;
|
||||||
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.mod.Mods.*;
|
import io.anuke.mindustry.mod.Mods.*;
|
||||||
@@ -17,9 +19,14 @@ public class ModsDialog extends FloatingDialog{
|
|||||||
public ModsDialog(){
|
public ModsDialog(){
|
||||||
super("$mods");
|
super("$mods");
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
|
|
||||||
|
buttons.addImageTextButton("$mods.report", Icon.link,
|
||||||
|
() -> Core.net.openURI(reportIssueURL))
|
||||||
|
.size(250f, 64f);
|
||||||
|
|
||||||
buttons.addImageTextButton("$mods.guide", Icon.wiki,
|
buttons.addImageTextButton("$mods.guide", Icon.wiki,
|
||||||
() -> Core.net.openURI(modGuideURL))
|
() -> Core.net.openURI(modGuideURL))
|
||||||
.size(290f, 64f);
|
.size(280f, 64f);
|
||||||
|
|
||||||
shown(this::setup);
|
shown(this::setup);
|
||||||
|
|
||||||
@@ -69,10 +76,16 @@ public class ModsDialog extends FloatingDialog{
|
|||||||
setup();
|
setup();
|
||||||
}).height(50f).margin(8f).width(130f);
|
}).height(50f).margin(8f).width(130f);
|
||||||
|
|
||||||
title.addImageButton(Icon.trash16Small, Styles.cleari, () -> ui.showConfirm("$confirm", "$mod.remove.confirm", () -> {
|
title.addImageButton(mod.workshopID != null ? Icon.linkSmall : Icon.trash16Small, Styles.cleari, () -> {
|
||||||
|
if(mod.workshopID == null){
|
||||||
|
ui.showConfirm("$confirm", "$mod.remove.confirm", () -> {
|
||||||
mods.removeMod(mod);
|
mods.removeMod(mod);
|
||||||
setup();
|
setup();
|
||||||
})).size(50f);
|
});
|
||||||
|
}else{
|
||||||
|
platform.viewListing(mod.workshopID);
|
||||||
|
}
|
||||||
|
}).size(50f);
|
||||||
}).growX().left().padTop(-14f).padRight(-14f);
|
}).growX().left().padTop(-14f).padRight(-14f);
|
||||||
|
|
||||||
t.row();
|
t.row();
|
||||||
@@ -107,5 +120,27 @@ public class ModsDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).margin(12f).width(500f);
|
}).margin(12f).width(500f);
|
||||||
|
|
||||||
|
//not well tested currently
|
||||||
|
if(Version.build == -1){
|
||||||
|
cont.row();
|
||||||
|
|
||||||
|
cont.addImageTextButton("$mod.import.github", Icon.github, () -> {
|
||||||
|
ui.showTextInput("$mod.import.github", "", "Anuken/ExampleMod", text -> {
|
||||||
|
Core.net.httpGet("http://api.github.com/repos/" + text + "/zipball/master", loc -> {
|
||||||
|
Core.net.httpGet(loc.getHeader("Location"), result -> {
|
||||||
|
try{
|
||||||
|
Streams.copyStream(result.getResultAsStream(), modDirectory.child(text.replace("/", "") + ".zip").write(false));
|
||||||
|
ui.loadAnd(() -> {
|
||||||
|
mods.reloadContent();
|
||||||
|
});
|
||||||
|
}catch(Exception e){
|
||||||
|
ui.showException(e);
|
||||||
|
}
|
||||||
|
}, ui::showException);
|
||||||
|
}, ui::showException);
|
||||||
|
});
|
||||||
|
}).margin(12f).width(500f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@ import io.anuke.arc.scene.ui.TextButton.*;
|
|||||||
import io.anuke.arc.scene.ui.layout.*;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.mindustry.core.GameState.*;
|
import io.anuke.mindustry.core.GameState.*;
|
||||||
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
@@ -225,7 +226,9 @@ public class SettingsMenuDialog extends SettingsDialog{
|
|||||||
|
|
||||||
game.checkPref("savecreate", true);
|
game.checkPref("savecreate", true);
|
||||||
|
|
||||||
if(steam){
|
game.checkPref("hints", true);
|
||||||
|
|
||||||
|
if(steam && !Version.modifier.contains("beta")){
|
||||||
game.checkPref("publichost", false, i -> {
|
game.checkPref("publichost", false, i -> {
|
||||||
platform.updateLobby();
|
platform.updateLobby();
|
||||||
});
|
});
|
||||||
@@ -252,6 +255,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
|||||||
});
|
});
|
||||||
graphics.sliderPref("fpscap", 240, 15, 245, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s)));
|
graphics.sliderPref("fpscap", 240, 15, 245, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s)));
|
||||||
graphics.sliderPref("chatopacity", 100, 0, 100, 5, s -> s + "%");
|
graphics.sliderPref("chatopacity", 100, 0, 100, 5, s -> s + "%");
|
||||||
|
graphics.sliderPref("lasersopacity", 100, 0, 100, 5, s -> s + "%");
|
||||||
|
|
||||||
if(!mobile){
|
if(!mobile){
|
||||||
graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b));
|
graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b));
|
||||||
@@ -297,7 +301,6 @@ public class SettingsMenuDialog extends SettingsDialog{
|
|||||||
graphics.checkPref("animatedshields", !mobile);
|
graphics.checkPref("animatedshields", !mobile);
|
||||||
}
|
}
|
||||||
graphics.checkPref("bloom", false, val -> renderer.toggleBloom(val));
|
graphics.checkPref("bloom", false, val -> renderer.toggleBloom(val));
|
||||||
graphics.checkPref("lasers", true);
|
|
||||||
graphics.checkPref("pixelate", false, val -> {
|
graphics.checkPref("pixelate", false, val -> {
|
||||||
if(val){
|
if(val){
|
||||||
Events.fire(Trigger.enablePixelation);
|
Events.fire(Trigger.enablePixelation);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import io.anuke.arc.*;
|
|||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
|
import io.anuke.arc.input.*;
|
||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.math.geom.*;
|
import io.anuke.arc.math.geom.*;
|
||||||
import io.anuke.arc.scene.*;
|
import io.anuke.arc.scene.*;
|
||||||
@@ -134,7 +135,7 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class View extends Group{
|
class View extends Group{
|
||||||
float panX = 0, panY = -200;
|
float panX = 0, panY = -200, lastZoom = -1;
|
||||||
boolean moved = false;
|
boolean moved = false;
|
||||||
ImageButton hoverNode;
|
ImageButton hoverNode;
|
||||||
Table infoTable = new Table();
|
Table infoTable = new Table();
|
||||||
@@ -205,12 +206,47 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dragged((x, y) -> {
|
TechTreeDialog.this.dragged((x, y) -> {
|
||||||
moved = true;
|
moved = true;
|
||||||
panX += x;
|
panX += x / getScaleX();
|
||||||
panY += y;
|
panY += y / getScaleY();
|
||||||
clamp();
|
clamp();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addListener(new InputListener(){
|
||||||
|
@Override
|
||||||
|
public boolean scrolled(InputEvent event, float x, float y, float amountX, float amountY){
|
||||||
|
setScale(Mathf.clamp(getScaleX() - amountY / 100f, 0.2f, 1f));
|
||||||
|
setOrigin(Align.center);
|
||||||
|
setTransform(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseMoved(InputEvent event, float x, float y){
|
||||||
|
requestScroll();
|
||||||
|
return super.mouseMoved(event, x, y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addListener(new ElementGestureListener(){
|
||||||
|
@Override
|
||||||
|
public void zoom(InputEvent event, float initialDistance, float distance){
|
||||||
|
if(lastZoom < 0){
|
||||||
|
lastZoom = getScaleX();
|
||||||
|
}
|
||||||
|
|
||||||
|
setScale(Mathf.clamp(distance / initialDistance * lastZoom, 0.2f, 1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){
|
||||||
|
lastZoom = getScaleX();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setOrigin(Align.center);
|
||||||
|
setTransform(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clamp(){
|
void clamp(){
|
||||||
@@ -308,9 +344,9 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void drawChildren(){
|
||||||
clamp();
|
clamp();
|
||||||
float offsetX = panX + width / 2f + x, offsetY = panY + height / 2f + y;
|
float offsetX = panX + width / 2f, offsetY = panY + height / 2f;
|
||||||
|
|
||||||
for(TechTreeNode node : nodes){
|
for(TechTreeNode node : nodes){
|
||||||
if(!node.visible) continue;
|
if(!node.visible) continue;
|
||||||
@@ -324,7 +360,7 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
super.draw();
|
super.drawChildren();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package io.anuke.mindustry.ui.dialogs;
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.scene.ui.layout.*;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
|
import io.anuke.mindustry.game.Objectives.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.type.Zone.*;
|
|
||||||
import io.anuke.mindustry.world.*;
|
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
@@ -38,8 +38,7 @@ public class ZoneInfoDialog extends FloatingDialog{
|
|||||||
|
|
||||||
if(!zone.unlocked()) return;
|
if(!zone.unlocked()) return;
|
||||||
|
|
||||||
ItemStack[] stacks = zone.getLaunchCost();
|
for(ItemStack stack : zone.getLaunchCost()){
|
||||||
for(ItemStack stack : stacks){
|
|
||||||
if(stack.amount == 0) continue;
|
if(stack.amount == 0) continue;
|
||||||
|
|
||||||
if(i++ % 2 == 0){
|
if(i++ % 2 == 0){
|
||||||
@@ -62,29 +61,32 @@ public class ZoneInfoDialog extends FloatingDialog{
|
|||||||
cont.table(req -> {
|
cont.table(req -> {
|
||||||
req.defaults().left();
|
req.defaults().left();
|
||||||
|
|
||||||
if(zone.zoneRequirements.length > 0){
|
Array<Objective> zones = zone.requirements.select(o -> !(o instanceof Unlock));
|
||||||
|
|
||||||
|
if(!zones.isEmpty()){
|
||||||
req.table(r -> {
|
req.table(r -> {
|
||||||
r.add("$complete").colspan(2).left();
|
r.add("$complete").colspan(2).left();
|
||||||
r.row();
|
r.row();
|
||||||
for(ZoneRequirement other : zone.zoneRequirements){
|
for(Objective o : zones){
|
||||||
r.addImage(Icon.terrain).padRight(4);
|
r.addImage(Icon.terrain).padRight(4);
|
||||||
r.add(Core.bundle.format("zone.requirement", other.wave, other.zone.localizedName())).color(Color.lightGray);
|
r.add(o.display()).color(Color.lightGray);
|
||||||
r.addImage(other.zone.bestWave() >= other.wave ? Icon.checkSmall : Icon.cancelSmall, other.zone.bestWave() >= other.wave ? Color.lightGray : Color.scarlet).padLeft(3);
|
r.addImage(o.complete() ? Icon.checkSmall : Icon.cancelSmall, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||||
r.row();
|
r.row();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
req.row();
|
req.row();
|
||||||
|
Array<Unlock> blocks = zone.requirements.select(o -> o instanceof Unlock).as(Unlock.class);
|
||||||
|
|
||||||
if(zone.blockRequirements.length > 0){
|
if(!blocks.isEmpty()){
|
||||||
req.table(r -> {
|
req.table(r -> {
|
||||||
r.add("$research.list").colspan(2).left();
|
r.add("$research.list").colspan(2).left();
|
||||||
r.row();
|
r.row();
|
||||||
for(Block block : zone.blockRequirements){
|
for(Unlock blocko : blocks){
|
||||||
r.addImage(block.icon(Cicon.small)).size(8 * 3).padRight(4);
|
r.addImage(blocko.block.icon(Cicon.small)).size(8 * 3).padRight(5);
|
||||||
r.add(block.localizedName).color(Color.lightGray);
|
r.add(blocko.block.localizedName).color(Color.lightGray).left();
|
||||||
r.addImage(data.isUnlocked(block) ? Icon.checkSmall : Icon.cancelSmall, data.isUnlocked(block) ? Color.lightGray : Color.scarlet).padLeft(3);
|
r.addImage(blocko.block.unlocked() ? Icon.checkSmall : Icon.cancelSmall, blocko.block.unlocked() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||||
r.row();
|
r.row();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +108,7 @@ public class ZoneInfoDialog extends FloatingDialog{
|
|||||||
t.left();
|
t.left();
|
||||||
t.add("$zone.resources").padRight(6);
|
t.add("$zone.resources").padRight(6);
|
||||||
|
|
||||||
if(zone.resources.length > 0){
|
if(zone.resources.size > 0){
|
||||||
t.table(r -> {
|
t.table(r -> {
|
||||||
t.left();
|
t.left();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -135,8 +137,8 @@ public class ZoneInfoDialog extends FloatingDialog{
|
|||||||
|
|
||||||
cont.row();
|
cont.row();
|
||||||
|
|
||||||
cont.addButton(zone.canConfigure() ? "$configure" : Core.bundle.format("configure.locked", zone.configureWave),
|
cont.addButton(zone.canConfigure() ? "$configure" : Core.bundle.format("configure.locked", zone.configureObjective.display()),
|
||||||
() -> loadout.show(zone.loadout.core().itemCapacity, zone::getStartingItems, zone::resetStartingItems, zone::updateLaunchCost, rebuildItems, item -> data.getItem(item) > 0 && item.type == ItemType.material)
|
() -> loadout.show(zone.loadout.core().itemCapacity, zone.getStartingItems(), zone::resetStartingItems, zone::updateLaunchCost, rebuildItems)
|
||||||
).fillX().pad(3).disabled(b -> !zone.canConfigure());
|
).fillX().pad(3).disabled(b -> !zone.canConfigure());
|
||||||
}
|
}
|
||||||
cont.marginRight(12f);
|
cont.marginRight(12f);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
//menu at top left
|
//menu at top left
|
||||||
parent.fill(cont -> {
|
parent.fill(cont -> {
|
||||||
|
cont.setName("overlaymarker");
|
||||||
cont.top().left();
|
cont.top().left();
|
||||||
|
|
||||||
if(mobile){
|
if(mobile){
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package io.anuke.mindustry.ui.fragments;
|
package io.anuke.mindustry.ui.fragments;
|
||||||
|
|
||||||
import io.anuke.arc.scene.Group;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.scene.event.Touchable;
|
import io.anuke.arc.scene.event.*;
|
||||||
import io.anuke.arc.scene.ui.layout.WidgetGroup;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
|
import io.anuke.mindustry.*;
|
||||||
|
|
||||||
/** Fragment for displaying overlays such as block inventories. */
|
/** Fragment for displaying overlays such as block inventories. */
|
||||||
public class OverlayFragment extends Fragment{
|
public class OverlayFragment{
|
||||||
public final BlockInventoryFragment inv;
|
public final BlockInventoryFragment inv;
|
||||||
public final BlockConfigFragment config;
|
public final BlockConfigFragment config;
|
||||||
|
|
||||||
@@ -17,10 +18,9 @@ public class OverlayFragment extends Fragment{
|
|||||||
config = new BlockConfigFragment();
|
config = new BlockConfigFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void add(){
|
||||||
public void build(Group parent){
|
|
||||||
group.setFillParent(true);
|
group.setFillParent(true);
|
||||||
parent.addChild(group);
|
Vars.ui.hudGroup.addChildBefore(Core.scene.find("overlaymarker"), group);
|
||||||
|
|
||||||
inv.build(group);
|
inv.build(group);
|
||||||
config.build(group);
|
config.build(group);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import io.anuke.arc.scene.event.*;
|
|||||||
import io.anuke.arc.scene.style.*;
|
import io.anuke.arc.scene.style.*;
|
||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.scene.ui.layout.*;
|
import io.anuke.arc.scene.ui.layout.*;
|
||||||
|
import io.anuke.arc.util.*;
|
||||||
|
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||||
import io.anuke.mindustry.entities.type.*;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
@@ -17,7 +19,7 @@ import io.anuke.mindustry.gen.*;
|
|||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.input.*;
|
import io.anuke.mindustry.input.*;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.ui.Styles;
|
import io.anuke.mindustry.ui.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
@@ -74,18 +76,22 @@ public class PlacementFragment extends Fragment{
|
|||||||
|
|
||||||
boolean gridUpdate(InputHandler input){
|
boolean gridUpdate(InputHandler input){
|
||||||
if(Core.input.keyDown(Binding.pick)){ //mouse eyedropper select
|
if(Core.input.keyDown(Binding.pick)){ //mouse eyedropper select
|
||||||
Tile tile = world.tileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
|
Tile tile = world.ltileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
|
||||||
|
Block tryRecipe = tile == null ? null : tile.block();
|
||||||
|
|
||||||
if(tile != null){
|
for(BuildRequest req : player.buildQueue()){
|
||||||
tile = tile.link();
|
if(!req.breaking && req.block.bounds(req.x, req.y, Tmp.r1).contains(Core.input.mouseWorld())){
|
||||||
Block tryRecipe = tile.block();
|
tryRecipe = req.block;
|
||||||
if(tryRecipe.isVisible() && unlocked(tryRecipe)){
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tryRecipe != null && tryRecipe.isVisible() && unlocked(tryRecipe)){
|
||||||
input.block = tryRecipe;
|
input.block = tryRecipe;
|
||||||
currentCategory = input.block.category;
|
currentCategory = input.block.category;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(!Core.input.keyDown(Binding.gridMode) || ui.chatfrag.chatOpen()) return false;
|
if(!Core.input.keyDown(Binding.gridMode) || ui.chatfrag.chatOpen()) return false;
|
||||||
if(Core.input.keyDown(Binding.gridModeShift)){ //select category
|
if(Core.input.keyDown(Binding.gridModeShift)){ //select category
|
||||||
@@ -151,6 +157,10 @@ public class PlacementFragment extends Fragment{
|
|||||||
Color color = state.rules.infiniteResources || (core != null && (core.items.has(block.requirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources)) ? Color.white : Color.gray;
|
Color color = state.rules.infiniteResources || (core != null && (core.items.has(block.requirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources)) ? Color.white : Color.gray;
|
||||||
button.forEach(elem -> elem.setColor(color));
|
button.forEach(elem -> elem.setColor(color));
|
||||||
button.setChecked(control.input.block == block);
|
button.setChecked(control.input.block == block);
|
||||||
|
|
||||||
|
if(state.rules.bannedBlocks.contains(block)){
|
||||||
|
button.forEach(elem -> elem.setColor(Color.darkGray));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
button.hovered(() -> hovered = block);
|
button.hovered(() -> hovered = block);
|
||||||
@@ -226,6 +236,15 @@ public class PlacementFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
}).growX().left().margin(3);
|
}).growX().left().margin(3);
|
||||||
|
|
||||||
|
if(state.rules.bannedBlocks.contains(lastDisplay)){
|
||||||
|
topTable.row();
|
||||||
|
topTable.table(b -> {
|
||||||
|
b.addImage(Icon.cancelSmall).padRight(2).color(Color.scarlet);
|
||||||
|
b.add("$banned");
|
||||||
|
b.left();
|
||||||
|
}).padTop(2).left();
|
||||||
|
}
|
||||||
|
|
||||||
}else if(tileDisplayBlock() != null){ //show selected tile
|
}else if(tileDisplayBlock() != null){ //show selected tile
|
||||||
lastDisplay = tileDisplayBlock();
|
lastDisplay = tileDisplayBlock();
|
||||||
topTable.table(t -> {
|
topTable.table(t -> {
|
||||||
@@ -250,7 +269,7 @@ public class PlacementFragment extends Fragment{
|
|||||||
blocksSelect.margin(4).marginTop(0);
|
blocksSelect.margin(4).marginTop(0);
|
||||||
blocksSelect.table(blocks -> blockTable = blocks).grow();
|
blocksSelect.table(blocks -> blockTable = blocks).grow();
|
||||||
blocksSelect.row();
|
blocksSelect.row();
|
||||||
blocksSelect.table(control.input::buildUI).name("inputTable").growX();
|
blocksSelect.table(control.input::buildPlacementUI).name("inputTable").growX();
|
||||||
}).fillY().bottom().touchable(Touchable.enabled);
|
}).fillY().bottom().touchable(Touchable.enabled);
|
||||||
frame.table(categories -> {
|
frame.table(categories -> {
|
||||||
categories.defaults().size(50f);
|
categories.defaults().size(50f);
|
||||||
@@ -301,7 +320,11 @@ public class PlacementFragment extends Fragment{
|
|||||||
returnArray.add(block);
|
returnArray.add(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
returnArray.sort((b1, b2) -> -Boolean.compare(unlocked(b1), unlocked(b2)));
|
returnArray.sort((b1, b2) -> {
|
||||||
|
int locked = -Boolean.compare(unlocked(b1), unlocked(b2));
|
||||||
|
if(locked != 0) return locked;
|
||||||
|
return Boolean.compare(state.rules.bannedBlocks.contains(b1), state.rules.bannedBlocks.contains(b2));
|
||||||
|
});
|
||||||
return returnArray;
|
return returnArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ import io.anuke.arc.util.ArcAnnotate.*;
|
|||||||
import io.anuke.arc.util.pooling.*;
|
import io.anuke.arc.util.pooling.*;
|
||||||
import io.anuke.mindustry.entities.*;
|
import io.anuke.mindustry.entities.*;
|
||||||
import io.anuke.mindustry.entities.effect.*;
|
import io.anuke.mindustry.entities.effect.*;
|
||||||
|
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||||
import io.anuke.mindustry.entities.type.*;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.input.InputHandler.*;
|
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.ui.*;
|
import io.anuke.mindustry.ui.*;
|
||||||
import io.anuke.mindustry.world.blocks.*;
|
import io.anuke.mindustry.world.blocks.*;
|
||||||
@@ -96,6 +96,8 @@ public class Block extends BlockStorage{
|
|||||||
public boolean targetable = true;
|
public boolean targetable = true;
|
||||||
/** Whether the overdrive core has any effect on this block. */
|
/** Whether the overdrive core has any effect on this block. */
|
||||||
public boolean canOverdrive = true;
|
public boolean canOverdrive = true;
|
||||||
|
/** Outlined icon color.*/
|
||||||
|
public Color outlineColor = Color.valueOf("404049");
|
||||||
/** Whether the icon region has an outline added. */
|
/** Whether the icon region has an outline added. */
|
||||||
public boolean outlineIcon = false;
|
public boolean outlineIcon = false;
|
||||||
/** Whether this block has a shadow under it. */
|
/** Whether this block has a shadow under it. */
|
||||||
@@ -385,6 +387,10 @@ public class Block extends BlockStorage{
|
|||||||
buildCost += stack.amount * stack.item.cost;
|
buildCost += stack.amount * stack.item.cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(consumes.has(ConsumeType.power)) hasPower = true;
|
||||||
|
if(consumes.has(ConsumeType.item)) hasItems = true;
|
||||||
|
if(consumes.has(ConsumeType.liquid)) hasLiquids = true;
|
||||||
|
|
||||||
setStats();
|
setStats();
|
||||||
setBars();
|
setBars();
|
||||||
|
|
||||||
@@ -661,17 +667,81 @@ public class Block extends BlockStorage{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getPlaceDraw(PlaceDraw draw, int rotation, int prevX, int prevY, int prevRotation){
|
public void drawRequest(BuildRequest req, Eachable<BuildRequest> list, boolean valid){
|
||||||
draw.region = icon(Cicon.full);
|
Draw.reset();
|
||||||
draw.scalex = draw.scaley = 1;
|
Draw.mixcol(!valid ? Pal.breakInvalid : Color.white, (!valid ? 0.4f : 0.24f) + Mathf.absin(Time.globalTime(), 6f, 0.28f));
|
||||||
draw.rotation = rotation;
|
Draw.alpha(1f);
|
||||||
|
drawRequestRegion(req, list);
|
||||||
|
Draw.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawRequestRegion(BuildRequest req, Eachable<BuildRequest> list){
|
||||||
|
TextureRegion reg = icon(Cicon.full);
|
||||||
|
Draw.rect(icon(Cicon.full), req.drawx(), req.drawy(),
|
||||||
|
reg.getWidth() * req.animScale * Draw.scl, reg.getHeight() * req.animScale * Draw.scl,
|
||||||
|
!rotate ? 0 : req.rotation * 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createIcons(PixmapPacker out, PixmapPacker editor){
|
public void createIcons(PixmapPacker packer, PixmapPacker editor){
|
||||||
super.createIcons(out, editor);
|
super.createIcons(packer, editor);
|
||||||
|
|
||||||
editor.pack(name + "-icon-editor", Core.atlas.getPixmap((AtlasRegion)icon(Cicon.full)).crop());
|
editor.pack(name + "-icon-editor", Core.atlas.getPixmap((AtlasRegion)icon(Cicon.full)).crop());
|
||||||
|
|
||||||
|
if(!synthetic()){
|
||||||
|
PixmapRegion image = Core.atlas.getPixmap((AtlasRegion)icon(Cicon.full));
|
||||||
|
color.set(image.getPixel(image.width/2, image.height/2));
|
||||||
|
}
|
||||||
|
|
||||||
|
getGeneratedIcons();
|
||||||
|
|
||||||
|
Pixmap last = null;
|
||||||
|
|
||||||
|
if(outlineIcon){
|
||||||
|
final int radius = 4;
|
||||||
|
PixmapRegion region = Core.atlas.getPixmap(getGeneratedIcons()[getGeneratedIcons().length-1]);
|
||||||
|
Pixmap out = new Pixmap(region.width, region.height);
|
||||||
|
Color color = new Color();
|
||||||
|
for(int x = 0; x < region.width; x++){
|
||||||
|
for(int y = 0; y < region.height; y++){
|
||||||
|
|
||||||
|
region.getPixel(x, y, color);
|
||||||
|
out.draw(x, y, color);
|
||||||
|
if(color.a < 1f){
|
||||||
|
boolean found = false;
|
||||||
|
outer:
|
||||||
|
for(int rx = -radius; rx <= radius; rx++){
|
||||||
|
for(int ry = -radius; ry <= radius; ry++){
|
||||||
|
if(Structs.inBounds(rx + x, ry + y, region.width, region.height) && Mathf.dst2(rx, ry) <= radius*radius && color.set(region.getPixel(rx + x, ry + y)).a > 0.01f){
|
||||||
|
found = true;
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found){
|
||||||
|
out.draw(x, y, outlineColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last = out;
|
||||||
|
|
||||||
|
packer.pack(name, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(generatedIcons.length > 1){
|
||||||
|
Pixmap base = Core.atlas.getPixmap(generatedIcons[0]).crop();
|
||||||
|
for(int i = 1; i < generatedIcons.length; i++){
|
||||||
|
if(i == generatedIcons.length - 1 && last != null){
|
||||||
|
base.drawPixmap(last);
|
||||||
|
}else{
|
||||||
|
base.draw(Core.atlas.getPixmap(generatedIcons[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packer.pack("block-" + name + "-full", base);
|
||||||
|
generatedIcons = null;
|
||||||
|
Arrays.fill(cicons, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Never use outside of the editor! */
|
/** Never use outside of the editor! */
|
||||||
@@ -724,6 +794,10 @@ public class Block extends BlockStorage{
|
|||||||
return ((size + 1) % 2) * tilesize / 2f;
|
return ((size + 1) % 2) * tilesize / 2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Rectangle bounds(int x, int y, Rectangle rect){
|
||||||
|
return rect.setSize(size * tilesize).setCenter(x * tilesize + offset(), y * tilesize + offset());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMultiblock(){
|
public boolean isMultiblock(){
|
||||||
return size > 1;
|
return size > 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ public class Build{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(state.rules.bannedBlocks.contains(type) && !(state.rules.waves && team == waveTeam)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if((type.solid || type.solidifes) && Units.anyEntities(x * tilesize + type.offset() - type.size*tilesize/2f, y * tilesize + type.offset() - type.size*tilesize/2f, type.size * tilesize, type.size*tilesize)){
|
if((type.solid || type.solidifes) && Units.anyEntities(x * tilesize + type.offset() - type.size*tilesize/2f, y * tilesize + type.offset() - type.size*tilesize/2f, type.size * tilesize, type.size*tilesize)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,10 +50,14 @@ public class Edges{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Tile getFacingEdge(Tile tile, Tile other){
|
public static Tile getFacingEdge(Tile tile, Tile other){
|
||||||
if(!tile.block().isMultiblock()) return tile;
|
return getFacingEdge(tile.block, tile.x, tile.y, other);
|
||||||
int size = tile.block().size;
|
}
|
||||||
return world.tile(tile.x + Mathf.clamp(other.x - tile.x, -(size - 1) / 2, (size / 2)),
|
|
||||||
tile.y + Mathf.clamp(other.y - tile.y, -(size - 1) / 2, (size / 2)));
|
public static Tile getFacingEdge(Block block, int tilex, int tiley, Tile other){
|
||||||
|
if(!block.isMultiblock()) return world.tile(tilex, tiley);
|
||||||
|
int size = block.size;
|
||||||
|
return world.tile(tilex + Mathf.clamp(other.x - tilex, -(size - 1) / 2, (size / 2)),
|
||||||
|
tiley + Mathf.clamp(other.y - tiley, -(size - 1) / 2, (size / 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector2[] getPixelPolygon(float radius){
|
public static Vector2[] getPixelPolygon(float radius){
|
||||||
|
|||||||
96
core/src/io/anuke/mindustry/world/blocks/Autotiler.java
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package io.anuke.mindustry.world.blocks;
|
||||||
|
|
||||||
|
import io.anuke.arc.function.*;
|
||||||
|
import io.anuke.arc.math.*;
|
||||||
|
import io.anuke.arc.math.geom.*;
|
||||||
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
|
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||||
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public interface Autotiler{
|
||||||
|
class AutotilerHolder{
|
||||||
|
static final int[] blendresult = new int[3];
|
||||||
|
static final BuildRequest[] directionals = new BuildRequest[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
default @Nullable int[] getTiling(BuildRequest req, Eachable<BuildRequest> list){
|
||||||
|
if(req.tile() == null) return null;
|
||||||
|
BuildRequest[] directionals = AutotilerHolder.directionals;
|
||||||
|
|
||||||
|
Arrays.fill(directionals, null);
|
||||||
|
list.each(other -> {
|
||||||
|
if(other.breaking || other == req) return;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for(Point2 point : Geometry.d4){
|
||||||
|
int x = req.x + point.x, y = req.y + point.y;
|
||||||
|
if(x >= other.x -(other.block.size - 1) / 2 && x <= other.x + (other.block.size / 2) && y >= other.y -(other.block.size - 1) / 2 && y <= other.y + (other.block.size / 2)){
|
||||||
|
directionals[i] = other;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return buildBlending(req.tile(), req.rotation, directionals);
|
||||||
|
}
|
||||||
|
|
||||||
|
default int[] buildBlending(Tile tile, int rotation, BuildRequest[] directional){
|
||||||
|
int[] blendresult = AutotilerHolder.blendresult;
|
||||||
|
blendresult[0] = 0;
|
||||||
|
blendresult[1] = blendresult[2] = 1;
|
||||||
|
int num =
|
||||||
|
(blends(tile, rotation, directional, 2) && blends(tile, rotation, directional, 1) && blends(tile, rotation, directional, 3)) ? 0 :
|
||||||
|
(blends(tile, rotation, directional, 1) && blends(tile, rotation, directional, 3)) ? 1 :
|
||||||
|
(blends(tile, rotation, directional, 1) && blends(tile, rotation, directional, 2)) ? 2 :
|
||||||
|
(blends(tile, rotation, directional, 3) && blends(tile, rotation, directional, 2)) ? 3 :
|
||||||
|
blends(tile, rotation, directional, 1) ? 4 :
|
||||||
|
blends(tile, rotation, directional, 3) ? 5 :
|
||||||
|
-1;
|
||||||
|
transformCase(num, blendresult);
|
||||||
|
return blendresult;
|
||||||
|
}
|
||||||
|
|
||||||
|
default void transformCase(int num, int[] bits){
|
||||||
|
if(num == 0){
|
||||||
|
bits[0] = 3;
|
||||||
|
}else if(num == 1){
|
||||||
|
bits[0] = 4;
|
||||||
|
}else if(num == 2){
|
||||||
|
bits[0] = 2;
|
||||||
|
}else if(num == 3){
|
||||||
|
bits[0] = 2;
|
||||||
|
bits[2] = -1;
|
||||||
|
}else if(num == 4){
|
||||||
|
bits[0] = 1;
|
||||||
|
bits[2] = -1;
|
||||||
|
}else if(num == 5){
|
||||||
|
bits[0] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean blends(Tile tile, int rotation, @Nullable BuildRequest[] directional, int direction){
|
||||||
|
int realDir = Mathf.mod(rotation - direction, 4);
|
||||||
|
if(directional != null && directional[realDir] != null){
|
||||||
|
BuildRequest req = directional[realDir];
|
||||||
|
if(blends(tile, rotation, req.x, req.y, req.rotation, req.block)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return blends(tile, rotation, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean blends(Tile tile, int rotation, int direction){
|
||||||
|
Tile other = tile.getNearby(Mathf.mod(rotation - direction, 4));
|
||||||
|
if(other != null) other = other.link();
|
||||||
|
return other != null && blends(tile, rotation, other.x, other.y, other.rotation(), other.block());
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean lookingAt(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||||
|
return (Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
|
||||||
|
|| (!otherblock.rotate || Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock);
|
||||||
|
}
|
||||||
@@ -110,8 +110,8 @@ public class BuildBlock extends Block{
|
|||||||
|
|
||||||
//if the target is constructible, begin constructing
|
//if the target is constructible, begin constructing
|
||||||
if(entity.cblock != null){
|
if(entity.cblock != null){
|
||||||
player.clearBuilding();
|
//player.clearBuilding();
|
||||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.rotation(), entity.cblock));
|
player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.rotation(), entity.cblock), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,13 @@ public class Floor extends Block{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(variants > 0){
|
||||||
|
for(int i = 0; i < variants; i++){
|
||||||
|
String rname = name + (i + 1);
|
||||||
|
editor.pack("editor-" + rname, Core.atlas.getPixmap(rname).crop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Color color = new Color();
|
Color color = new Color();
|
||||||
Color color2 = new Color();
|
Color color2 = new Color();
|
||||||
PixmapRegion image = Core.atlas.getPixmap((AtlasRegion)generateIcons()[0]);
|
PixmapRegion image = Core.atlas.getPixmap((AtlasRegion)generateIcons()[0]);
|
||||||
@@ -204,10 +211,6 @@ public class Floor extends Block{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean eq(int i){
|
|
||||||
return (eq & (1 << Mathf.mod(i, 8))) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextureRegion edge(Floor block, int x, int y){
|
TextureRegion edge(Floor block, int x, int y){
|
||||||
return block.edges()[x][2 - y];
|
return block.edges()[x][2 - y];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,19 +23,19 @@ public class OreBlock extends OverlayFloor{
|
|||||||
/** For mod use only!*/
|
/** For mod use only!*/
|
||||||
public OreBlock(String name){
|
public OreBlock(String name){
|
||||||
super(name);
|
super(name);
|
||||||
|
variants = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setup(Item ore){
|
public void setup(Item ore){
|
||||||
this.localizedName = ore.localizedName();
|
this.localizedName = ore.localizedName();
|
||||||
this.itemDrop = ore;
|
this.itemDrop = ore;
|
||||||
this.variants = 3;
|
|
||||||
this.color.set(ore.color);
|
this.color.set(ore.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@OverrideCallSuper
|
@OverrideCallSuper
|
||||||
public void createIcons(PixmapPacker out, PixmapPacker editor){
|
public void createIcons(PixmapPacker out, PixmapPacker editor){
|
||||||
for(int i = 0; i < 3; i++){
|
for(int i = 0; i < variants; i++){
|
||||||
Pixmap image = new Pixmap(32, 32);
|
Pixmap image = new Pixmap(32, 32);
|
||||||
PixmapRegion shadow = Core.atlas.getPixmap(itemDrop.name + (i + 1));
|
PixmapRegion shadow = Core.atlas.getPixmap(itemDrop.name + (i + 1));
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package io.anuke.mindustry.world.blocks.distribution;
|
package io.anuke.mindustry.world.blocks.distribution;
|
||||||
|
|
||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.geom.*;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
@@ -16,11 +16,8 @@ public class ArmoredConveyor extends Conveyor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean blends(Tile tile, int direction){
|
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||||
Tile other = tile.getNearby(Mathf.mod(tile.rotation() - direction, 4));
|
return otherblock.outputsItems() && (Point2.equals(tile.x + Geometry.d4(rotation).x, tile.y + Geometry.d4(rotation).y, otherx, othery)
|
||||||
if(other != null) other = other.link();
|
|| ((!otherblock.rotate && Edges.getFacingEdge(otherblock, otherx, othery, tile).relativeTo(tile) == tile.rotation()) || Point2.equals(otherx + Geometry.d4(otherrot).x, othery + Geometry.d4(otherrot).y, tile.x, tile.y)));
|
||||||
|
|
||||||
return other != null && other.block().outputsItems()
|
|
||||||
&& ((tile.getNearby(tile.rotation()) == other) || ((!other.block().rotate && Edges.getFacingEdge(other, tile).relativeTo(tile) == tile.rotation()) || (other.block().rotate && other.getNearby(other.rotation()) == tile)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
package io.anuke.mindustry.world.blocks.distribution;
|
package io.anuke.mindustry.world.blocks.distribution;
|
||||||
|
|
||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.graphics.g2d.Draw;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.graphics.g2d.TextureRegion;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.mindustry.entities.type.TileEntity;
|
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||||
import io.anuke.mindustry.type.Liquid;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.world.blocks.LiquidBlock;
|
import io.anuke.mindustry.world.*;
|
||||||
import io.anuke.mindustry.world.modules.LiquidModule;
|
import io.anuke.mindustry.world.blocks.*;
|
||||||
|
import io.anuke.mindustry.world.modules.*;
|
||||||
|
|
||||||
public class Conduit extends LiquidBlock{
|
public class Conduit extends LiquidBlock implements Autotiler{
|
||||||
protected final int timerFlow = timers++;
|
protected final int timerFlow = timers++;
|
||||||
|
|
||||||
protected TextureRegion[] topRegions = new TextureRegion[7];
|
protected TextureRegion[] topRegions = new TextureRegion[7];
|
||||||
@@ -39,29 +40,33 @@ public class Conduit extends LiquidBlock{
|
|||||||
super.onProximityUpdate(tile);
|
super.onProximityUpdate(tile);
|
||||||
|
|
||||||
ConduitEntity entity = tile.entity();
|
ConduitEntity entity = tile.entity();
|
||||||
entity.blendbits = 0;
|
int[] bits = buildBlending(tile, tile.rotation(), null);
|
||||||
entity.blendrot = 0;
|
entity.blendbits = bits[0];
|
||||||
|
|
||||||
if(blends(tile, 2) && blends(tile, 1) && blends(tile, 3)){
|
|
||||||
entity.blendbits = 3;
|
|
||||||
}else if(blends(tile, 1) && blends(tile, 3)){
|
|
||||||
entity.blendbits = 6;
|
|
||||||
}else if(blends(tile, 1) && blends(tile, 2)){
|
|
||||||
entity.blendbits = 2;
|
|
||||||
}else if(blends(tile, 3) && blends(tile, 2)){
|
|
||||||
entity.blendbits = 4;
|
|
||||||
}else if(blends(tile, 1)){
|
|
||||||
entity.blendbits = 5;
|
|
||||||
}else if(blends(tile, 3)){
|
|
||||||
entity.blendbits = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean blends(Tile tile, int direction){
|
@Override
|
||||||
Tile other = tile.getNearby(Mathf.mod(tile.rotation() - direction, 4));
|
public void drawRequestRegion(BuildRequest req, Eachable<BuildRequest> list){
|
||||||
if(other != null) other = other.link();
|
int[] bits = getTiling(req, list);
|
||||||
|
|
||||||
return other != null && other.block().hasLiquids && other.block().outputsLiquid && ((tile.getNearby(tile.rotation()) == other) || (!other.block().rotate || other.getNearby(other.rotation()) == tile));
|
if(bits == null) return;
|
||||||
|
|
||||||
|
Draw.colorl(0.34f);
|
||||||
|
Draw.alpha(0.5f);
|
||||||
|
Draw.rect(botRegions[bits[0]], req.drawx(), req.drawy(), req.rotation * 90);
|
||||||
|
Draw.color();
|
||||||
|
|
||||||
|
|
||||||
|
Draw.rect(topRegions[bits[0]], req.drawx(), req.drawy(), req.rotation * 90);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transformCase(int num, int[] bits){
|
||||||
|
bits[0] = num == 0 ? 3 : num == 1 ? 6 : num == 2 ? 2 : num == 3 ? 4 : num == 4 ? 5 : num == 5 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||||
|
return otherblock.hasLiquids && otherblock.outputsLiquid && lookingAt(tile, rotation, otherx, othery, otherrot, otherblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -113,7 +118,6 @@ public class Conduit extends LiquidBlock{
|
|||||||
public static class ConduitEntity extends TileEntity{
|
public static class ConduitEntity extends TileEntity{
|
||||||
public float smoothLiquid;
|
public float smoothLiquid;
|
||||||
|
|
||||||
byte blendbits;
|
int blendbits;
|
||||||
int blendrot;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,24 +2,26 @@ package io.anuke.mindustry.world.blocks.distribution;
|
|||||||
|
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.graphics.g2d.*;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.math.*;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.math.geom.*;
|
import io.anuke.arc.math.geom.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
|
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
|
||||||
import io.anuke.mindustry.entities.type.*;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.gen.*;
|
import io.anuke.mindustry.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.input.InputHandler.*;
|
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
import io.anuke.mindustry.world.blocks.*;
|
||||||
import io.anuke.mindustry.world.meta.*;
|
import io.anuke.mindustry.world.meta.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class Conveyor extends Block{
|
public class Conveyor extends Block implements Autotiler{
|
||||||
private static final float itemSpace = 0.4f;
|
private static final float itemSpace = 0.4f;
|
||||||
private static final float minmove = 1f / (Short.MAX_VALUE - 2);
|
private static final float minmove = 1f / (Short.MAX_VALUE - 2);
|
||||||
private static ItemPos drawpos = new ItemPos();
|
private static ItemPos drawpos = new ItemPos();
|
||||||
@@ -27,6 +29,8 @@ public class Conveyor extends Block{
|
|||||||
private static ItemPos pos2 = new ItemPos();
|
private static ItemPos pos2 = new ItemPos();
|
||||||
private final Vector2 tr1 = new Vector2();
|
private final Vector2 tr1 = new Vector2();
|
||||||
private final Vector2 tr2 = new Vector2();
|
private final Vector2 tr2 = new Vector2();
|
||||||
|
private final int[] blendresult = new int[3];
|
||||||
|
private final BuildRequest[] directionals = new BuildRequest[4];
|
||||||
|
|
||||||
private TextureRegion[][] regions = new TextureRegion[7][4];
|
private TextureRegion[][] regions = new TextureRegion[7][4];
|
||||||
|
|
||||||
@@ -90,55 +94,25 @@ public class Conveyor extends Block{
|
|||||||
super.onProximityUpdate(tile);
|
super.onProximityUpdate(tile);
|
||||||
|
|
||||||
ConveyorEntity entity = tile.entity();
|
ConveyorEntity entity = tile.entity();
|
||||||
entity.blendbits = 0;
|
int[] bits = buildBlending(tile, tile.rotation(), null);
|
||||||
entity.blendsclx = entity.blendscly = 1;
|
entity.blendbits = bits[0];
|
||||||
|
entity.blendsclx = bits[1];
|
||||||
if(blends(tile, 2) && blends(tile, 1) && blends(tile, 3)){
|
entity.blendscly = bits[2];
|
||||||
entity.blendbits = 3;
|
|
||||||
}else if(blends(tile, 1) && blends(tile, 3)){
|
|
||||||
entity.blendbits = 4;
|
|
||||||
}else if(blends(tile, 1) && blends(tile, 2)){
|
|
||||||
entity.blendbits = 2;
|
|
||||||
}else if(blends(tile, 3) && blends(tile, 2)){
|
|
||||||
entity.blendbits = 2;
|
|
||||||
entity.blendscly = -1;
|
|
||||||
}else if(blends(tile, 1)){
|
|
||||||
entity.blendbits = 1;
|
|
||||||
entity.blendscly = -1;
|
|
||||||
}else if(blends(tile, 3)){
|
|
||||||
entity.blendbits = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getPlaceDraw(PlaceDraw draw, int rotation, int prevX, int prevY, int prevRotation){
|
public void drawRequestRegion(BuildRequest req, Eachable<BuildRequest> list){
|
||||||
draw.rotation = rotation;
|
int[] bits = getTiling(req, list);
|
||||||
draw.scalex = draw.scaley = 1;
|
|
||||||
|
|
||||||
int blendbits = 0;
|
if(bits == null) return;
|
||||||
|
|
||||||
if(blends(rotation, 1, prevX, prevY, prevRotation)){
|
TextureRegion region = regions[bits[0]][0];
|
||||||
blendbits = 1;
|
Draw.rect(region, req.drawx(), req.drawy(), region.getWidth() * bits[1] * Draw.scl, region.getHeight() * bits[2] * Draw.scl, req.rotation * 90);
|
||||||
draw.scaley = -1;
|
|
||||||
}else if(blends(rotation, 3, prevX, prevY, prevRotation)){
|
|
||||||
blendbits = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw.rotation = rotation;
|
@Override
|
||||||
draw.region = regions[blendbits][0];
|
public boolean blends(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||||
}
|
return otherblock.outputsItems() && lookingAt(tile, rotation, otherx, othery, otherrot, otherblock);
|
||||||
|
|
||||||
protected boolean blends(int rotation, int offset, int prevX, int prevY, int prevRotation){
|
|
||||||
Point2 left = Geometry.d4(rotation - offset);
|
|
||||||
return left.equals(prevX, prevY) && prevRotation == Mathf.mod(rotation + offset, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean blends(Tile tile, int direction){
|
|
||||||
Tile other = tile.getNearby(Mathf.mod(tile.rotation() - direction, 4));
|
|
||||||
if(other != null) other = other.link();
|
|
||||||
|
|
||||||
return other != null && other.block().outputsItems()
|
|
||||||
&& ((tile.getNearby(tile.rotation()) == other) || (!other.block().rotate || other.getNearby(other.rotation()) == tile));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -232,8 +232,8 @@ public class MassDriver extends Block{
|
|||||||
int maxTransfer = Math.min(entity.items.get(content.item(i)), ((MassDriver)tile.block()).itemCapacity - totalUsed);
|
int maxTransfer = Math.min(entity.items.get(content.item(i)), ((MassDriver)tile.block()).itemCapacity - totalUsed);
|
||||||
data.items[i] = maxTransfer;
|
data.items[i] = maxTransfer;
|
||||||
totalUsed += maxTransfer;
|
totalUsed += maxTransfer;
|
||||||
|
entity.items.remove(content.item(i), maxTransfer);
|
||||||
}
|
}
|
||||||
entity.items.clear();
|
|
||||||
|
|
||||||
float angle = tile.angleTo(target);
|
float angle = tile.angleTo(target);
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import static io.anuke.mindustry.Vars.content;
|
|||||||
|
|
||||||
public class Sorter extends Block{
|
public class Sorter extends Block{
|
||||||
private static Item lastItem;
|
private static Item lastItem;
|
||||||
|
protected boolean invert;
|
||||||
|
|
||||||
public Sorter(String name){
|
public Sorter(String name){
|
||||||
super(name);
|
super(name);
|
||||||
@@ -40,16 +41,6 @@ public class Sorter extends Block{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
|
||||||
public static void setSorterItem(Player player, Tile tile, Item item){
|
|
||||||
if(!Units.canInteract(player, tile)) return;
|
|
||||||
SorterEntity entity = tile.entity();
|
|
||||||
if(entity != null){
|
|
||||||
entity.sortItem = item;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configured(Tile tile, Player player, int value){
|
public void configured(Tile tile, Player player, int value){
|
||||||
tile.<SorterEntity>entity().sortItem = content.item(value);
|
tile.<SorterEntity>entity().sortItem = content.item(value);
|
||||||
@@ -92,7 +83,7 @@ public class Sorter extends Block{
|
|||||||
if(dir == -1) return null;
|
if(dir == -1) return null;
|
||||||
Tile to;
|
Tile to;
|
||||||
|
|
||||||
if(item == entity.sortItem){
|
if((item == entity.sortItem) != invert){
|
||||||
//prevent 3-chains
|
//prevent 3-chains
|
||||||
if(isSame(dest, source) && isSame(dest, dest.getNearby(dir))){
|
if(isSame(dest, source) && isSame(dest, dest.getNearby(dir))){
|
||||||
return null;
|
return null;
|
||||||
@@ -115,12 +106,10 @@ public class Sorter extends Block{
|
|||||||
}else{
|
}else{
|
||||||
if(dest.rotation() == 0){
|
if(dest.rotation() == 0){
|
||||||
to = a;
|
to = a;
|
||||||
if(flip)
|
if(flip) dest.rotation((byte)1);
|
||||||
dest.rotation((byte)1);
|
|
||||||
}else{
|
}else{
|
||||||
to = b;
|
to = b;
|
||||||
if(flip)
|
if(flip) dest.rotation((byte)0);
|
||||||
dest.rotation((byte)0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,20 @@
|
|||||||
package io.anuke.mindustry.world.blocks.power;
|
package io.anuke.mindustry.world.blocks.power;
|
||||||
|
|
||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.graphics.Color;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.graphics.g2d.Draw;
|
import io.anuke.arc.graphics.g2d.*;
|
||||||
import io.anuke.arc.graphics.g2d.TextureRegion;
|
import io.anuke.arc.math.*;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.Time;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.content.Fx;
|
import io.anuke.mindustry.entities.*;
|
||||||
import io.anuke.mindustry.entities.Effects;
|
import io.anuke.mindustry.entities.Effects.*;
|
||||||
import io.anuke.mindustry.entities.type.TileEntity;
|
import io.anuke.mindustry.entities.type.*;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.type.Liquid;
|
import io.anuke.mindustry.world.*;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.consumers.*;
|
||||||
import io.anuke.mindustry.world.consumers.ConsumeItemFilter;
|
import io.anuke.mindustry.world.meta.*;
|
||||||
import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter;
|
|
||||||
import io.anuke.mindustry.world.meta.BlockStat;
|
|
||||||
import io.anuke.mindustry.world.meta.StatUnit;
|
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.content;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
import static io.anuke.mindustry.Vars.tilesize;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Power generation block which can use items, liquids or both as input sources for power production.
|
* Power generation block which can use items, liquids or both as input sources for power production.
|
||||||
@@ -33,17 +29,26 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
|||||||
/** Maximum liquid used per frame. */
|
/** Maximum liquid used per frame. */
|
||||||
protected float maxLiquidGenerate = 0.4f;
|
protected float maxLiquidGenerate = 0.4f;
|
||||||
|
|
||||||
protected Effects.Effect generateEffect = Fx.generatespark;
|
protected Effect generateEffect = Fx.generatespark;
|
||||||
protected Effects.Effect explodeEffect = Fx.generatespark;
|
protected Effect explodeEffect = Fx.generatespark;
|
||||||
protected Color heatColor = Color.valueOf("ff9b59");
|
protected Color heatColor = Color.valueOf("ff9b59");
|
||||||
protected TextureRegion topRegion, liquidRegion;
|
protected TextureRegion topRegion, liquidRegion;
|
||||||
protected boolean randomlyExplode = true;
|
protected boolean randomlyExplode = true;
|
||||||
|
protected boolean defaults = false;
|
||||||
|
|
||||||
public ItemLiquidGenerator(boolean hasItems, boolean hasLiquids, String name){
|
public ItemLiquidGenerator(boolean hasItems, boolean hasLiquids, String name){
|
||||||
super(name);
|
super(name);
|
||||||
this.hasItems = hasItems;
|
this.hasItems = hasItems;
|
||||||
this.hasLiquids = hasLiquids;
|
this.hasLiquids = hasLiquids;
|
||||||
|
|
||||||
|
setDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemLiquidGenerator(String name){
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setDefaults(){
|
||||||
if(hasItems){
|
if(hasItems){
|
||||||
consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true, false);
|
consumes.add(new ConsumeItemFilter(item -> getItemEfficiency(item) >= minItemEfficiency)).update(false).optional(true, false);
|
||||||
}
|
}
|
||||||
@@ -51,6 +56,16 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
|||||||
if(hasLiquids){
|
if(hasLiquids){
|
||||||
consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, maxLiquidGenerate)).update(false).optional(true, false);
|
consumes.add(new ConsumeLiquidFilter(liquid -> getLiquidEfficiency(liquid) >= minLiquidEfficiency, maxLiquidGenerate)).update(false).optional(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaults = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(){
|
||||||
|
if(!defaults){
|
||||||
|
setDefaults();
|
||||||
|
}
|
||||||
|
super.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||