Merge branch 'master' into crater

This commit is contained in:
Patrick 'Quezler' Mounier
2020-02-10 12:09:14 +01:00
15 changed files with 153 additions and 682 deletions

View File

@ -81,7 +81,7 @@ public class AndroidLauncher extends AndroidApplication{
if(VERSION.SDK_INT >= VERSION_CODES.Q){
Intent intent = new Intent(open ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(extension.equals("zip") ? "application/zip" : "*/*");
intent.setType(extension.equals("zip") && !open ? "application/zip" : "*/*");
addResultListener(i -> startActivityForResult(intent, i), (code, in) -> {
if(code == Activity.RESULT_OK && in != null && in.getData() != null){
Uri uri = in.getData();

View File

@ -1,297 +0,0 @@
package mindustry.annotations.impl;
import arc.struct.*;
import arc.util.*;
import com.squareup.javapoet.*;
import com.squareup.javapoet.TypeSpec.*;
import com.sun.source.tree.*;
import mindustry.annotations.Annotations.*;
import mindustry.annotations.*;
import mindustry.annotations.util.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
@SupportedAnnotationTypes({
"mindustry.annotations.Annotations.EntityDef",
"mindustry.annotations.Annotations.EntityInterface",
"mindustry.annotations.Annotations.BaseComponent"
})
public class EntityProcess extends BaseProcessor{
Array<Definition> definitions = new Array<>();
Array<Stype> baseComponents;
ObjectMap<Stype, Array<Stype>> componentDependencies = new ObjectMap<>();
ObjectMap<Stype, Array<Stype>> defComponents = new ObjectMap<>();
ObjectSet<String> imports = new ObjectSet<>();
{
rounds = 2;
}
@Override
public void process(RoundEnvironment env) throws Exception{
//round 1: get component classes and generate interfaces for them
if(round == 1){
baseComponents = types(BaseComponent.class);
Array<Stype> allDefs = types(EntityDef.class);
ObjectSet<Stype> allComponents = new ObjectSet<>();
//find all components used...
for(Stype type : allDefs){
allComponents.addAll(allComponents(type));
}
//add all components w/ dependencies
allComponents.addAll(types(Depends.class).map(s -> Array.withArrays(getDependencies(s), s)).flatten());
//add component imports
for(Stype comp : allComponents){
imports.addAll(getImports(comp.e));
}
//create component interfaces
for(Stype component : allComponents){
TypeSpec.Builder inter = TypeSpec.interfaceBuilder(interfaceName(component)).addModifiers(Modifier.PUBLIC).addAnnotation(EntityInterface.class);
//implement extra interfaces these components may have, e.g. position
for(Stype extraInterface : component.interfaces()){
inter.addSuperinterface(extraInterface.mirror());
}
//implement super interfaces
Array<Stype> depends = getDependencies(component);
for(Stype type : depends){
inter.addSuperinterface(ClassName.get(packageName, interfaceName(type)));
}
for(Svar field : component.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE) && !e.is(Modifier.TRANSIENT))){
String cname = Strings.capitalize(field.name());
//getter
inter.addMethod(MethodSpec.methodBuilder("get" + cname).addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC).returns(field.tname()).build());
//setter
if(!field.is(Modifier.FINAL)) inter.addMethod(MethodSpec.methodBuilder("set" + cname).addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC).addParameter(field.tname(), field.name()).build());
}
//add utility methods to interface
for(Smethod method : component.methods()){
inter.addMethod(MethodSpec.methodBuilder(method.name())
.addExceptions(method.thrownt())
.addTypeVariables(method.typeVariables().map(TypeVariableName::get))
.returns(method.ret().toString().equals("void") ? TypeName.VOID : method.retn())
.addParameters(method.params().map(v -> ParameterSpec.builder(v.tname(), v.name())
.build())).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).build());
}
write(inter);
}
//look at each definition
for(Stype type : allDefs){
if(!type.name().endsWith("Def")){
err("All entity def names must end with 'Def'", type.e);
}
String name = type.name().replace("Def", "Gen"); //TODO remove 'gen'
TypeSpec.Builder builder = TypeSpec.classBuilder(name).addModifiers(Modifier.PUBLIC, Modifier.FINAL);
Array<Stype> components = allComponents(type);
ObjectMap<String, Array<Smethod>> methods = new ObjectMap<>();
//add all components
for(Stype comp : components){
//write fields to the class; ignoring transient ones
Array<Svar> fields = comp.fields().select(f -> !f.is(Modifier.TRANSIENT));
for(Svar f : fields){
VariableTree tree = f.tree();
FieldSpec.Builder fbuilder = FieldSpec.builder(f.tname(), f.name());
//add initializer if it exists
if(tree.getInitializer() != null){
fbuilder.initializer(tree.getInitializer().toString());
}
builder.addField(fbuilder.build());
}
//get all utility methods from components
for(Smethod elem : comp.methods()){
methods.getOr(elem.toString(), Array::new).add(elem);
}
}
//add all methods from components
for(ObjectMap.Entry<String, Array<Smethod>> entry : methods){
//representative method
Smethod first = entry.value.first();
//build method using same params/returns
MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(Modifier.PUBLIC, Modifier.FINAL);
mbuilder.addTypeVariables(first.typeVariables().map(TypeVariableName::get));
mbuilder.returns(first.retn());
mbuilder.addExceptions(first.thrownt());
for(Svar var : first.params()){
mbuilder.addParameter(var.tname(), var.name());
}
//only write the block if it's a void method with several entries
boolean writeBlock = first.ret().toString().equals("void") && entry.value.size > 1;
if(entry.value.first().is(Modifier.ABSTRACT) && entry.value.size == 1){
err(entry.value.first().up().getSimpleName() + " declares an abstract method. This method must be implemented in another component", entry.value.first());
}
for(Smethod elem : entry.value){
if(elem.is(Modifier.ABSTRACT)) continue;
//get all statements in the method, copy them over
MethodTree methodTree = elem.tree();
BlockTree blockTree = methodTree.getBody();
String str = blockTree.toString();
//name for code blocks in the methods
String blockName = elem.up().getSimpleName().toString().toLowerCase().replace("comp", "");
//skip empty blocks
if(str.replace("{", "").replace("\n", "").replace("}", "").replace("\t", "").replace(" ", "").isEmpty()){
continue;
}
//wrap scope to prevent variable leakage
if(writeBlock){
//replace return; with block break
str = str.replace("return;", "break " + blockName + ";");
mbuilder.addCode(blockName + ": {\n");
}
//trim block
str = str.substring(2, str.length() - 1);
//make sure to remove braces here
mbuilder.addCode(str);
//end scope
if(writeBlock) mbuilder.addCode("}\n");
}
builder.addMethod(mbuilder.build());
}
definitions.add(new Definition(builder, type));
}
}else{
//round 2: generate actual classes and implement interfaces
Array<Stype> interfaces = types(EntityInterface.class);
//implement each definition
for(Definition def : definitions){
Array<Stype> components = allComponents(def.base);
//get interface for each component
for(Stype comp : components){
//implement the interface
Stype inter = interfaces.find(i -> i.name().equals(interfaceName(comp)));
def.builder.addSuperinterface(inter.tname());
//generate getter/setter for each method
for(Smethod method : inter.methods()){
if(method.name().length() <= 3) continue;
String var = Strings.camelize(method.name().substring(3));
//make sure it's a real variable
if(!Array.with(def.builder.fieldSpecs).contains(f -> f.name.equals(var))) continue;
if(method.name().startsWith("get")){
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build());
}else if(method.name().startsWith("set")){
def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("this." + var + " = " + var).build());
}
}
}
write(def.builder, imports.asArray());
}
}
}
Array<String> getImports(Element elem){
return Array.with(trees.getPath(elem).getCompilationUnit().getImports()).map(Object::toString);
}
/** @return interface for a component type */
String interfaceName(Stype comp){
String suffix = "Comp";
if(!comp.name().endsWith(suffix)){
err("All components must have names that end with 'Comp'.", comp.e);
}
return comp.name().substring(0, comp.name().length() - suffix.length()) + "c";
}
/** @return all components that a entity def has */
Array<Stype> allComponents(Stype type){
if(!defComponents.containsKey(type)){
//get base defs
Array<Stype> components = Array.with(mirrors(type)).map(Stype::of);
ObjectSet<Stype> out = new ObjectSet<>();
for(Stype comp : components){
//get dependencies for each def, add them
out.add(comp);
out.addAll(getDependencies(comp));
}
defComponents.put(type, out.asArray());
}
return defComponents.get(type);
}
Array<Stype> getDependencies(Stype component){
if(!componentDependencies.containsKey(component)){
ObjectSet<Stype> out = new ObjectSet<>();
out.addAll(component.superclasses());
//get dependency classes
if(component.annotation(Depends.class) != null){
try{
component.annotation(Depends.class).value();
}catch(MirroredTypesException e){
out.addAll(Array.with(e.getTypeMirrors()).map(Stype::of));
}
}
//out now contains the base dependencies; finish constructing the tree
ObjectSet<Stype> result = new ObjectSet<>();
for(Stype type : out){
result.add(type);
result.addAll(getDependencies(type));
}
if(component.annotation(BaseComponent.class) == null){
result.addAll(baseComponents);
}
componentDependencies.put(component, result.asArray());
}
return componentDependencies.get(component);
}
TypeMirror[] mirrors(Stype type){
try{
type.annotation(EntityDef.class).value();
}catch(MirroredTypesException e){
return e.getTypeMirrors().toArray(new TypeMirror[0]);
}
throw new IllegalArgumentException("Missing components: " + type);
}
class Definition{
final TypeSpec.Builder builder;
final Stype base;
public Definition(Builder builder, Stype base){
this.builder = builder;
this.base = base;
}
}
}

View File

@ -3,7 +3,7 @@ credits = Tekijät
contributors = Kääntäjät ja avustajat
discord = Liity Mindustryn Discordiin!
link.discord.description = Mindustryn virallinen Discord-keskusteluhuone
link.reddit.description = Mindustry subreddit
link.reddit.description = Mindustryn alireddit
link.github.description = Pelin lähdekoodi
link.changelog.description = Lista päivityksien muutoksista
link.dev-builds.description = Epävakaat kehitysversiot
@ -21,15 +21,15 @@ gameover.pvp = [accent] {0}[] joukkue voittaa!
highscore = [accent]Uusi ennätys!
copied = Kopioitu.
load.sound = Ääni
load.map = Kartat
load.image = Kuvat
load.content = Sisältö
load.system = Systeemi
load.mod = Modit
load.scripts = Skriptit
load.sound = Ääniä
load.map = Karttoja
load.image = Kuvia
load.content = Sisältöä
load.system = Järjestelmää
load.mod = Modeja
load.scripts = Skriptejä
be.update = A new Bleeding Edge build is available:
be.update = Uusi kehitysversio on saatavilla:
be.update.confirm = Lataa se ja käynnistä peli uudelleen?
be.updating = Päivitetään...
be.ignore = Sivuuta
@ -37,20 +37,20 @@ be.noupdates = Ei päivityksiä saatavilla.
be.check = Tarkista päivityksiä
schematic = Kaavio
schematic.add = Tallenna Kaavio...
schematic.add = Tallenna kaavio...
schematics = Kaaviot
schematic.replace = Kaavio tällä nimellä on jo olemassa. Haluatko korvata sen?
schematic.import = Tuo Kaavio...
schematic.exportfile = Luo Tiedosto
schematic.importfile = Tuo Tiedosto
schematic.browseworkshop = Selaa Työpajaa
schematic.copy = Kopioi Leikepöydälle
schematic.copy.import = Tou Leikepöydälle
schematic.shareworkshop = Jaa työpajaan
schematic.import = Tuo kaavio...
schematic.exportfile = Vie tiedosto
schematic.importfile = Tuo tiedosto
schematic.browseworkshop = Selaa Workshoppia
schematic.copy = Kopioi leikepöydälle
schematic.copy.import = Tuo leikepöydäl
schematic.shareworkshop = Jaa Workshoppiin
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Käännä Kaavio
schematic.saved = Kaavio tallennettu.
schematic.delete.confirm = Tämä kaavio poistetaan.
schematic.rename = Uudelleennimeä Kaavio
schematic.rename = Nimeä kaavio uudelleen
schematic.info = {0}x{1}, {2} palikkaa
stat.wave = Tasoja voitettu:[accent] {0}
@ -62,7 +62,7 @@ stat.delivered = Resursseja laukaistu:
stat.rank = Lopullinen arvosana: [accent]{0}
launcheditems = [accent]Laukaistut tavarat
launchinfo = [unlaunched][[LAUNCH] your core to obtain the items indicated in blue.
launchinfo = [unlaunched][[LAUKAISE] ytimesi saadaksesi sinisellä merkityt tavarat.
map.delete = Oletko varma että haluat poistaa kartan "[accent]{0}[]"?
level.highscore = Ennätys: [accent]{0}
level.select = Tason valinta
@ -82,12 +82,12 @@ position = Sijainti
close = Sulje
website = Verkkosivu
quit = Poistu
save.quit = Tallenna ja Poistu
save.quit = Tallenna ja poistu
maps = Kartat
maps.browse = Selaa Karttoja
maps.browse = Selaa karttoja
continue = Jatka
maps.none = [lightgray]Karttoja ei löytynyt!
invalid = Invalidi
invalid = Virheellinen
pickcolor = Valitse väri
preparingconfig = Preparing Config
preparingcontent = Preparing Content
@ -95,29 +95,29 @@ uploadingcontent = Uploading Content
uploadingpreviewfile = Uploading Preview File
committingchanges = Comitting Changes
done = Valmis
feature.unsupported = Sinun laitteesi ei tue tätä toimintoa.
feature.unsupported = Laitteesi ei tue tätä toimintoa.
mods.alphainfo = Pidä mielessä että modit ovat alpha-tilassa, ja[scarlet] ne voivat olla virheellisiä[].\nRaportoi kaikki virheet Mindustry GitHub-sivuille tai Discordiin.
mods.alpha = [accent](Alpha)
mods = Modit
mods.none = [LIGHT_GRAY]Modeja ei löytynyt!
mods.guide = Modaamisen opas
mods.guide = Modaamisopas
mods.report = Raportoi ohjelmistovirhe
mods.openfolder = Avaa Modikansio
mods.openfolder = Avaa modikansio
mod.enabled = [lightgray]Käytössä
mod.disabled = [scarlet]Epäkäytössä
mod.disable = Laita pois päältä
mod.delete.error = Modia ei pystynyt poistamaan. Tiedosto voi olla käytössä.
mod.requiresversion = [scarlet]Tarvitsee vähintää pelin version: [accent]{0}
mod.disabled = [scarlet]Pois käytöstä
mod.disable = Poista käytössä
mod.delete.error = Modia ei pystytty poistamaan. Tiedosto voi olla käytössä.
mod.requiresversion = [scarlet]Tarvitsee vähintään pelin version: [accent]{0}
mod.missingdependencies = [scarlet]Tarvitsee nämä modit: {0}
mod.erroredcontent = [scarlet]Sisältö Virheet
mod.erroredcontent = [scarlet]Sisältövirheet
mod.errors = Virheitä on tapahtunut pelin ladatessa.
mod.noerrorplay = [scarlet]Sinulla on virheellisiä modeja.[] Joko poista ne käytöstä tai korjaa virheet.
mod.nowdisabled = [scarlet]Mod '{0}' is missing dependencies:[accent] {1}\n[lightgray]These mods need to be downloaded first.\nThis mod will be automatically disabled.
mod.enable = Käytä
mod.requiresrestart = Peli suljetaan jotta muutokset voisivat toteutua.
mod.reloadrequired = [scarlet]Vaatii Uudelleenkäynnistystä
mod.import = Tuo Modi
mod.import = Tuo modi
mod.import.github = Import GitHub Mod
mod.item.remove = This item is part of the[accent] '{0}'[] mod. To remove it, uninstall that mod.
mod.remove.confirm = Tämä modi poistetaan.
@ -170,7 +170,7 @@ hosts.discovering.any = Etsitään Pelejä
server.refreshing = Päivitetään palvelimen tietoja
hosts.none = [lightgray]Paikallisia pelejä ei löytynyt!
host.invalid = [scarlet]Isäntään ei voitu yhdistää.
trace = Seuraa Pelaajaa
trace = Seuraa pelaajaa
trace.playername = Pelaajanimi: [accent]{0}
trace.ip = IP-osoite: [accent]{0}
trace.id = Uniikki tunniste: [accent]{0}
@ -188,8 +188,8 @@ server.outdated = [crimson]Vanhentunut palvelin![]
server.outdated.client = [crimson]Vanhentunut asiakasohjelma![]
server.version = [gray]v{0} {1}
server.custombuild = [yellow]Custom Build
confirmban = Oletko varma että haluat potkia tämän pelaajan?
confirmkick = Oletko varma että haluat poistaa tämän pelaajan?
confirmban = Oletko varma että haluat antaa porttikiellon tälle pelaajalle?
confirmkick = Oletko varma että haluat potkia tämän pelaajan?
confirmvotekick = Oletko varma että haluat äänestää tämän pelaajan potkituksi?
confirmunban = Oletko varma että haluat päästää tämän pelaajan takaisin?
confirmadmin = Oletko varma että haluat antaa pelaajalle hallinto-oikeuksia?
@ -208,32 +208,32 @@ server.port = Portti:
server.addressinuse = Address already in use!
server.invalidport = Invalid port number!
server.error = [crimson]Error hosting server: [accent]{0}
save.new = New Save
save.new = Uusi tallennus
save.overwrite = Are you sure you want to overwrite\nthis save slot?
overwrite = Overwrite
save.none = No saves found!
saveload = Tallennetaan...
savefail = Failed to save game!
savefail = Pelin tallentaminen epäonnistui!
save.delete.confirm = Are you sure you want to delete this save?
save.delete = Delete
save.export = Export Save
save.import.invalid = [accent]This save is invalid!
save.import.fail = [crimson]Failed to import save: [accent]{0}
save.export.fail = [crimson]Failed to export save: [accent]{0}
save.import = Tuo Tallennus
save.import = Tuo tallennus
save.newslot = Tallennuksen nimi:
save.rename = Nimeä uudelleen
save.rename.text = Uusi nimi:
selectslot = Valitse tallennus.
slot = [accent]Paikka {0}
editmessage = Edit Message
editmessage = Muokkaa viestiä
save.corrupted = [accent]Tallennustiedosto korruptoitunut tai viallinen!\nJos olet päivittänyt juuri pelisi, tämä on todennäköisesti muutos tallennusmuodossa [scarlet]eikä[] virhe.
empty = <tyhjä>
on = Päällä
off = Pois
save.autosave = Automaattitallennus: {0}
save.map = Kartta: {0}
save.wave = Aalto {0}
save.wave = Taso {0}
save.mode = Gamemode: {0}
save.date = Viimeksi tallennettu: {0}
save.playtime = Peliaika: {0}
@ -308,15 +308,15 @@ editor.waves = Tasot:
editor.rules = Säännöt:
editor.generation = Generaatio:
editor.ingame = Muokka pelin sisällä
editor.publish.workshop = Julkaise työpajaan
editor.publish.workshop = Julkaise Workshoppiin
editor.newmap = Uusi kartta
workshop = Työpaja
workshop = Workshop
waves.title = Tasot
waves.remove = Poista
waves.never = <ei koskaan>
waves.every = every
waves.waves = wave(s)
waves.perspawn = per spawni
waves.perspawn = per syntymispiste
waves.to = to
waves.boss = Pomo
waves.preview = Esikatselu
@ -324,13 +324,13 @@ waves.edit = Muokkaa...
waves.copy = Kopioi leikepöydälle
waves.load = Lataa leikepöydältä
waves.invalid = Invalid waves in clipboard.
waves.copied = Aallot kopioitu.
waves.copied = Tasot kopioitu.
waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout.
editor.default = [lightgray]<Default>
details = Yksityiskohdat...
edit = Muokkaa...
editor.name = Nimi:
editor.spawn = Spawni yksikkö
editor.spawn = Luo yksikkö
editor.removeunit = Poista yksikkö
editor.teams = Joukkueet
editor.errorload = Virhe ladattaessa tiedostoa:\n[accent]{0}
@ -431,8 +431,8 @@ fps = FPS: {0}
ping = Ping: {0}ms
language.restart = Please restart your game for the language settings to take effect.
settings = Asetukset
tutorial = Tutoriaali
tutorial.retake = Uusita Tutoriaali
tutorial = Perehdytys
tutorial.retake = Pelaa perehdytys uudelleen
editor = Editori
mapeditor = Kartan Editori
@ -449,8 +449,8 @@ launch = < LAUNCH >
launch.title = Onnistunut laukaisu
launch.next = [lightgray]next opportunity at wave {0}
launch.unable2 = [scarlet]Unable to LAUNCH.[]
launch.confirm = Tämä laukaisee kaikki resourssit ytimestäsi.\nEt voi enää palata takaisin.
launch.skip.confirm = Jos ohitat nyt, voit laukaista vasta myöhemmissä tasoissa.
launch.confirm = Tämä laukaisee kaikki resurssit ytimestäsi.\nEt voi enää palata takaisin.
launch.skip.confirm = Jos ohitat nyt, voit laukaista vasta myöhemmillä tasoilla.
uncover = Paljasta
configure = Configure Loadout
bannedblocks = Kielletyt Palikat
@ -530,60 +530,60 @@ error.title = [crimson]An error has occured
error.crashtitle = An error has occured
blocks.input = Sisääntulo
blocks.output = Ulostulo
blocks.booster = Boostaa
blocks.booster = Tehostaja
block.unknown = [lightgray]???
blocks.powercapacity = Energiakapasiteetti
blocks.powershot = Energiaa/Ammus
blocks.damage = Vahinko
blocks.targetsair = Hyökkää Ilmaan
blocks.targetsground = Hyökkää Maahan
blocks.targetsair = Hyökkää ilmaan
blocks.targetsground = Hyökkää maahan
blocks.itemsmoved = Liikkumisnopeus
blocks.launchtime = Aika Laukaisujen Välillä
blocks.launchtime = Aika laukaisujen välillä
blocks.shootrange = Kantama
blocks.size = Koko
blocks.liquidcapacity = Neste Kapasiteetti
blocks.powerrange = Energia Kantama
blocks.powerconnections = Maksimi konnektio määrä
blocks.poweruse = Energian Käyttö
blocks.liquidcapacity = Nestekapasiteetti
blocks.powerrange = Energiakantama
blocks.powerconnections = Maksimimäärä yhdistyksiä
blocks.poweruse = Energian käyttö
blocks.powerdamage = Energia/Vahinko
blocks.itemcapacity = Tavara Kapasiteetti
blocks.basepowergeneration = Kanta Enegian Generointi
blocks.productiontime = Produktion Aika
blocks.repairtime = Kokonaisen Palikan Korjaus Aika
blocks.speedincrease = Nopeuden Kasvu
blocks.itemcapacity = Tavarakapasiteetti
blocks.basepowergeneration = Perus energiantuotto
blocks.productiontime = Tuotantoaika
blocks.repairtime = Kokonaisen palikan korjausaika
blocks.speedincrease = Nopeuden kasvu
blocks.range = Etäisyys
blocks.drilltier = Porattavat
blocks.drillspeed = Kanta Poran Nopeus
blocks.boosteffect = Boostaamisen Vaikutus
blocks.maxunits = Maksimi Määrä Yksikköjä
blocks.boosteffect = Tehostamisem vaikutus
blocks.maxunits = Maksimimäärä yksikköjä
blocks.health = Elämäpisteet
blocks.buildtime = Rakentamisen Aika
blocks.buildcost = Rakentamisen Hinta
blocks.buildtime = Rakentamisaika
blocks.buildcost = Rakentamishinta
blocks.inaccuracy = Epätarkkuus
blocks.shots = Ammusta
blocks.reload = Ammusta/Sekunnissa
blocks.reload = Ammusta/sekunnissa
blocks.ammo = Ammus
bar.drilltierreq = Parempi Pora Vaadittu
bar.drillspeed = Poran Nopeus: {0}/s
bar.pumpspeed = Pumpun Nopeus: {0}/s
bar.drilltierreq = Parempi pora vaadittu
bar.drillspeed = Poran nopeus: {0}/s
bar.pumpspeed = Pumpun nopeus: {0}/s
bar.efficiency = Tehokkuus: {0}%
bar.powerbalance = Energia: {0}/s
bar.powerstored = Säilöttynä: {0}/{1}
bar.poweramount = Energia: {0}
bar.poweroutput = Energian Ulostulo: {0}
bar.poweroutput = Energiantuotto: {0}
bar.items = Tavaroita: {0}
bar.capacity = Kapasiteetti: {0}
bar.liquid = Neste
bar.heat = Lämpö
bar.power = Energia
bar.progress = Rakennuksen Edistys
bar.progress = Rakennuksen edistys
bar.spawned = Yksikköjä: {0}/{1}
bar.input = Sisääntulo
bar.output = Ulostulo
bullet.damage = [stat]{0}[lightgray] Vahinko
bullet.splashdamage = [stat]{0}[lightgray] Alue vahinko ~[stat] {1}[lightgray] palikkaa
bullet.splashdamage = [stat]{0}[lightgray] Aluevahinko ~[stat] {1}[lightgray] palikkaa
bullet.incendiary = [stat]sytyttävä
bullet.homing = [stat]itseohjautuva
bullet.shock = [stat]shokki
@ -591,15 +591,15 @@ bullet.frag = [stat]sirpaloituva
bullet.knockback = [stat]{0}[lightgray] knockback
bullet.freezing = [stat]jäädyttävä
bullet.tarred = [stat]tervattu
bullet.multiplier = [stat]{0}[lightgray]x ammusten multiplikaatio
bullet.reload = [stat]{0}[lightgray]x ammunta nopeus
bullet.multiplier = [stat]{0}[lightgray]x ammusten kerroin
bullet.reload = [stat]{0}[lightgray]x ampumisnopeus
unit.blocks = palikat
unit.powersecond = energia yksikköä/sekunti
unit.liquidsecond = neste yksikköä/sekunti
unit.powersecond = energiayksikköä/sekunti
unit.liquidsecond = nesteyksikköä/sekunti
unit.itemssecond = esinettä/sekunti
unit.liquidunits = neste yksikköä
unit.powerunits = energia yksikköä
unit.liquidunits = nesteyksikköä
unit.powerunits = energiayksikköä
unit.degrees = astetta
unit.seconds = sekunttia
unit.persecond = /s
@ -614,25 +614,25 @@ category.liquids = Neste
category.items = Tavarat
category.crafting = Ulos/Sisääntulo
category.shooting = Ammunta
category.optional = Mahdolliset Lumoukset
category.optional = Mahdolliset parannukset
setting.landscape.name = Lukitse tasavaakaan
setting.shadows.name = Varjot
setting.blockreplace.name = Automaattisia Palikka Suosituksia
setting.linear.name = Lineararien Filteeraus
setting.linear.name = Lineaarinen suodatus
setting.hints.name = Vihjeet
setting.buildautopause.name = Automaattisest Pysäytä Rakentaessa
setting.animatedwater.name = Animoitu Vesi
setting.animatedshields.name = Animoitu Kilpi
setting.animatedwater.name = Animoitu vesi
setting.animatedshields.name = Animoidut kilvet
setting.antialias.name = Antialiaasi[lightgray] (vaatii uudelleenkäynnistyksen)[]
setting.indicators.name = Vihollis/Puolulais Indikaattorit
setting.autotarget.name = Automaatinen Tähtäys
setting.keyboard.name = Hiiri+Näppäimistö Kontrollit
setting.touchscreen.name = Kosketusnäyttö kontrollit
setting.keyboard.name = Hiiri+Näppäimistö -ohjaus
setting.touchscreen.name = Kosketusnäyttöohjaus
setting.fpscap.name = Maksimi FPS
setting.fpscap.none = Ei Mitään
setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Koko[lightgray] (vaatii uudelleenkäynnistyksen)[]
setting.swapdiagonal.name = Aina Vino Korvaus
setting.swapdiagonal.name = Aina vino korvaus
setting.difficulty.training = Treeni
setting.difficulty.easy = Helppo
setting.difficulty.normal = Keskivaikea
@ -641,10 +641,10 @@ setting.difficulty.insane = Järjetön
setting.difficulty.name = Vaikeustaso:
setting.screenshake.name = Näytön keikkuminen
setting.effects.name = Naytön Efektit
setting.destroyedblocks.name = Näytä Tuhoutuneet Palikat
setting.destroyedblocks.name = Näytä tuhoutuneet palikat
setting.conveyorpathfinding.name = Conveyor Placement Pathfinding
setting.coreselect.name = Allow Schematic Cores
setting.sensitivity.name = Kontrollin Herkkyys
setting.sensitivity.name = Ohjauksen herkkyys
setting.saveinterval.name = Tallennuksen Aikaväli
setting.seconds = {0} Sekunttia
setting.blockselecttimeout.name = Block Select Timeout
@ -652,35 +652,35 @@ setting.milliseconds = {0} millisekunttia
setting.fullscreen.name = Fullscreen
setting.borderlesswindow.name = Borderless Window[lightgray] (vaatii uudelleenkäynnistyksen)
setting.fps.name = Näytä FPS
setting.blockselectkeys.name = Bäytä Palikan Selektio Kontrollit
setting.blockselectkeys.name = Näytä palikan valintaohjaimet
setting.vsync.name = VSync
setting.pixelate.name = Pixeloi[lightgray] (poistaa animaation käytöstä)
setting.minimap.name = Näytä Minimappi
setting.minimap.name = Näytä pienoiskartta
setting.position.name = Näytä pelaajan sijainti
setting.musicvol.name = Musiikin Äänenvoimakkuus
setting.ambientvol.name = Tausta Äänet
setting.mutemusic.name = Sulje Musiikki
setting.sfxvol.name = SFX Volyymi
setting.mutesound.name = Sulje Äänet
setting.musicvol.name = Musiikin äänenvoimakkuus
setting.ambientvol.name = Taustaäänet
setting.mutemusic.name = Mykistä musiikki
setting.sfxvol.name = SFX-voimakkuus
setting.mutesound.name = Mykistä äänet
setting.crashreport.name = Send Anonymous Crash Reports
setting.savecreate.name = Luo Automaattisesti Tallennukset
setting.savecreate.name = Luo tallenuksia automaattisesti
setting.publichost.name = Public Game Visibility
setting.chatopacity.name = Chatin Läpinäkymättömyys
setting.lasersopacity.name = Energia Laaserin Läpinäkymattämyys
setting.playerchat.name = Näytä Pelinsisäinen Keskustelu
setting.chatopacity.name = Keskustelun läpinäkymättömyys
setting.lasersopacity.name = Energia laserin läpinäkymättömyys
setting.playerchat.name = Näytä pelinsisäinen keskustelu
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.cancel = Peruuta ja Poistu
uiscale.cancel = Peruuta ja poistu
setting.bloom.name = Bloom
keybind.title = Rebind Keys
keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only basic movement is supported.
category.general.name = General
category.view.name = View
category.multiplayer.name = Multiplayer
command.attack = Hyökkää
command.rally = Kutsu Koolle
command.retreat = Palaa
category.multiplayer.name = Moninpeli
command.attack = Hyökkäys
command.rally = Kokoontuminen
command.retreat = Perääntyminen
placement.blockselectkeys = \n[lightgray]Key: [{0},
keybind.clear_building.name = Clear Building
keybind.press = Press a key...
@ -711,7 +711,7 @@ keybind.block_select_07.name = Category/Block Select 7
keybind.block_select_08.name = Category/Block Select 8
keybind.block_select_09.name = Category/Block Select 9
keybind.block_select_10.name = Category/Block Select 10
keybind.fullscreen.name = Vaihda Fullscreen
keybind.fullscreen.name = Vaihda kokonäyttötilaan
keybind.select.name = Select/Shoot
keybind.diagonal_placement.name = Diagonal Placement
keybind.pick.name = Pick Block
@ -722,8 +722,8 @@ keybind.zoom.name = Zoom
keybind.menu.name = Menu
keybind.pause.name = Pause
keybind.pause_building.name = Pause/Resume Building
keybind.minimap.name = Minimappi
keybind.chat.name = Chatti
keybind.minimap.name = Pienoiskartta
keybind.chat.name = Keskustelu
keybind.player_list.name = Player list
keybind.console.name = Console
keybind.rotate.name = Rotate
@ -736,9 +736,9 @@ keybind.drop_unit.name = Drop Unit
keybind.zoom_minimap.name = Zoom minimap
mode.help.title = Description of modes
mode.survival.name = Survival
mode.survival.description = Normaali moodi. Rajoitettu määrä resursseja ja tasoilla on aika.\n[gray]Vaatii vihollis spawneja kartassa.
mode.survival.description = Normaali tila. Rajoitettu määrä resursseja ja tasoilla on aika.\n[gray]Vaatii vihollisten syntymispisteen kartassa.
mode.sandbox.name = Hiekkalaatikko
mode.sandbox.description = Ikuisesti resursseja ja tasoilla ei ole aikaa.
mode.sandbox.description = Ikuisesti resursseja ja tasoja ei ole ajastettu.
mode.editor.name = Editori
mode.pvp.name = PvP
mode.pvp.description = Fight against other players locally.\n[gray]Requires at least 2 differently-colored cores in the map to play.
@ -746,9 +746,9 @@ mode.attack.name = Attack
mode.attack.description = Destroy the enemy's base. No waves.\n[gray]Requires a red core in the map to play.
mode.custom = Custom Rules
rules.infiniteresources = Ikuisesti Resursseja
rules.reactorexplosions = Reaktori Räjähdykset
rules.wavetimer = Tasojen Aikaraja
rules.infiniteresources = Ikuiset resurssit
rules.reactorexplosions = Reaktorien räjähtäminen
rules.wavetimer = Tasojen aikaraja
rules.waves = Tasot
rules.attack = Attack Mode
rules.enemyCheat = Infinite AI (Red Team) Resources
@ -791,11 +791,11 @@ item.titanium.name = Titaani
item.thorium.name = Torium
item.silicon.name = Pii
item.plastanium.name = Plastaniumi
item.phase-fabric.name = Kiihde Kuitu
item.surge-alloy.name = Taite Seos
item.spore-pod.name = Itiö Palko
item.phase-fabric.name = Kiihdekuitu
item.surge-alloy.name = Taiteseos
item.spore-pod.name = Itiöpalko
item.sand.name = Hiekka
item.blast-compound.name = Räjähde Yhdiste
item.blast-compound.name = Räjähdeyhdiste
item.pyratite.name = Pyratiitti
item.metaglass.name = Metallilasi
item.scrap.name = Romu
@ -824,7 +824,7 @@ mech.trident-ship.name = Trident
mech.trident-ship.weapon = Bomb Bay
mech.glaive-ship.name = Glaive
mech.glaive-ship.weapon = Flame Repeater
item.corestorable = [lightgray]Säilöttävissä Ytimeen: {0}
item.corestorable = [lightgray]Säilöttävissä ytimeen: {0}
item.explosiveness = [lightgray]Räjädysmäisyys: {0}%
item.flammability = [lightgray]Flammability: {0}%
item.radioactivity = [lightgray]Radioactivity: {0}%
@ -832,12 +832,12 @@ unit.health = [lightgray]Elämäpisteet: {0}
unit.speed = [lightgray]Nopeus: {0}
mech.weapon = [lightgray]Ase: {0}
mech.health = [lightgray]Elämäpisteet: {0}
mech.itemcapacity = [lightgray]Tavara Kapasiteetti: {0}
mech.minespeed = [lightgray]Louhimis Nopeus: {0}%
mech.minepower = [lightgray]Louhimis Voima: {0}
mech.ability = [lightgray]Spesiaalikyky: {0}
mech.buildspeed = [lightgray]Rakennus Nopeus: {0}%
liquid.heatcapacity = [lightgray]Lämpö Kapasiteetti: {0}
mech.itemcapacity = [lightgray]Tavarakapasiteetti: {0}
mech.minespeed = [lightgray]Louhimisnopeus: {0}%
mech.minepower = [lightgray]Louhimisvoima: {0}
mech.ability = [lightgray]Erityiskyky: {0}
mech.buildspeed = [lightgray]Rakentamisnopeus: {0}%
liquid.heatcapacity = [lightgray]Lämpökapasiteetti: {0}
liquid.viscosity = [lightgray]Tahmeus: {0}
liquid.temperature = [lightgray]Lämpö: {0}
@ -865,21 +865,21 @@ block.scrap-wall-huge.name = Huge Scrap Wall
block.scrap-wall-gigantic.name = Gigantic Scrap Wall
block.thruster.name = Thruster
block.kiln.name = Kiln
block.graphite-press.name = Grafiitti Puristin
block.multi-press.name = Multi-Puristin
block.graphite-press.name = Grafiittipuristin
block.multi-press.name = Monipuristin
block.constructing = {0} [lightgray](Rakentamassa)
block.spawn.name = Vihollis Spawni
block.spawn.name = Vihollisten syntymispiste
block.core-shard.name = Ydin: Siru
block.core-foundation.name = Ydin: Pohjaus
block.core-nucleus.name = Ydin: Tuma
block.deepwater.name = Syvä Vesi
block.deepwater.name = Syvä vesi
block.water.name = Vesi
block.tainted-water.name = Pilattu Vesi
block.tainted-water.name = Pilaantunut vesi
block.darksand-tainted-water.name = Dark Sand Tainted Water
block.tar.name = Terva
block.stone.name = Kivi
block.sand.name = Hiekka
block.darksand.name = Tumma Hiekka
block.darksand.name = Tumma hiekka
block.ice.name = Jää
block.snow.name = Lumi
block.craters.name = Kraatterit

View File

@ -172,8 +172,13 @@ hosts.discovering.any = Ricerca partite
server.refreshing = Aggiornamento del server
hosts.none = [lightgray]Nessuna partita locale trovata!
host.invalid = [scarlet]Impossibile connettersi all'host.
trace = Traccia giocatore
trace.playername = Nome del giocatore: [accent]{0}
servers.local = Server Locali
servers.remote = Server Remoti
servers.global = Server Globali
trace = Traccia Giocatore
trace.playername = Nome del Giocatore: [accent]{0}
trace.ip = IP: [accent]{0}
trace.id = ID univoco: [accent]{0}
trace.mobile = Client Mobile: [accent]{0}
@ -183,11 +188,11 @@ server.bans = Lista Bans
server.bans.none = Nessun giocatore bandito trovato!
server.admins = Amministratori
server.admins.none = Nessun amministratore trovato!
server.add = Aggiungi server
server.add = Aggiungi Server
server.delete = Sei sicuro di voler eliminare questo server?
server.edit = Modifica server
server.outdated = [crimson]Server obsoleto![]
server.outdated.client = [crimson]Client obsoleto![]
server.edit = Modifica Server
server.outdated = [crimson]Server Obsoleto![]
server.outdated.client = [crimson]Client Obsoleto![]
server.version = [gray]v{0} {1}
server.custombuild = [yellow]Build Personalizzata
confirmban = Sei sicuro di voler bandire questo giocatore?

View File

@ -59,7 +59,7 @@ public class Blocks implements ContentList{
//transport
conveyor, titaniumConveyor, plastaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router, overflowGate, underflowGate, massDriver,
//liquids
//liquid
mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit,
//power

View File

@ -1,231 +0,0 @@
package mindustry.entities.def;
import arc.graphics.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.Bits;
import arc.struct.*;
import arc.util.*;
import arc.util.pooling.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.ctype.*;
import mindustry.entities.bullet.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.type.*;
import java.io.*;
import static mindustry.Vars.content;
public class EntityComps{
@Depends({HealthComp.class, VelComp.class, StatusComp.class})
class UnitComp{
}
class OwnerComp{
Entityc owner;
}
@Depends({TimedComp.class})
class BulletComp{
BulletType bullet;
void init(){
bullet.init();
}
}
abstract class TimedComp extends EntityComp implements Scaled{
float time, lifetime;
void update(){
time = Math.min(time + Time.delta(), lifetime);
if(time >= lifetime){
remove();
}
}
@Override
public float fin(){
return time / lifetime;
}
}
class HealthComp{
float health, maxHealth;
boolean dead;
float healthf(){
return health / maxHealth;
}
}
abstract class PosComp implements Position{
float x, y;
void set(float x, float y){
this.x = x;
this.y = y;
}
}
@Depends(PosComp.class)
class VelComp{
//transient fields act as imports from any other component clases; these are ignored by the generator
transient float x, y;
final Vec2 vel = new Vec2();
void update(){
x += vel.x;
y += vel.y;
vel.scl(0.9f);
}
}
@Depends(PosComp.class)
class HitboxComp{
transient float x, y;
float hitSize;
boolean collides(Hitboxc other){
return Intersector.overlapsRect(x - hitSize/2f, y - hitSize/2f, hitSize, hitSize,
other.getX() - other.getHitSize()/2f, other.getY() - other.getHitSize()/2f, other.getHitSize(), other.getHitSize());
}
}
@Depends(PosComp.class)
class StatusComp{
private Array<StatusEntry> statuses = new Array<>();
private Bits applied = new Bits(content.getBy(ContentType.status).size);
private float speedMultiplier;
private float damageMultiplier;
private float armorMultiplier;
void apply(StatusEffect effect, float duration){
if(effect == StatusEffects.none || effect == null || isImmune(effect)) return; //don't apply empty or immune effects
if(statuses.size > 0){
//check for opposite effects
for(StatusEntry entry : statuses){
//extend effect
if(entry.effect == effect){
entry.time = Math.max(entry.time, duration);
return;
}else if(entry.effect.reactsWith(effect)){ //find opposite
StatusEntry.tmp.effect = entry.effect;
//TODO unit cannot be null here
entry.effect.getTransition(null, effect, entry.time, duration, StatusEntry.tmp);
entry.time = StatusEntry.tmp.time;
if(StatusEntry.tmp.effect != entry.effect){
entry.effect = StatusEntry.tmp.effect;
}
//stop looking when one is found
return;
}
}
}
//otherwise, no opposites found, add direct effect
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
entry.set(effect, duration);
statuses.add(entry);
}
boolean isImmune(StatusEffect effect){
return false;
}
Color getStatusColor(){
if(statuses.size == 0){
return Tmp.c1.set(Color.white);
}
float r = 0f, g = 0f, b = 0f;
for(StatusEntry entry : statuses){
r += entry.effect.color.r;
g += entry.effect.color.g;
b += entry.effect.color.b;
}
return Tmp.c1.set(r / statuses.size, g / statuses.size, b / statuses.size, 1f);
}
void update(){
applied.clear();
speedMultiplier = damageMultiplier = armorMultiplier = 1f;
if(statuses.isEmpty()) return;
statuses.eachFilter(entry -> {
entry.time = Math.max(entry.time - Time.delta(), 0);
applied.set(entry.effect.id);
if(entry.time <= 0){
Pools.free(entry);
return true;
}else{
speedMultiplier *= entry.effect.speedMultiplier;
armorMultiplier *= entry.effect.armorMultiplier;
damageMultiplier *= entry.effect.damageMultiplier;
//TODO unit can't be null
entry.effect.update(null, entry.time);
}
return false;
});
}
boolean hasEffect(StatusEffect effect){
return applied.get(effect.id);
}
void writeSave(DataOutput stream) throws IOException{
stream.writeByte(statuses.size);
for(StatusEntry entry : statuses){
stream.writeByte(entry.effect.id);
stream.writeFloat(entry.time);
}
}
void readSave(DataInput stream, byte version) throws IOException{
for(StatusEntry effect : statuses){
Pools.free(effect);
}
statuses.clear();
byte amount = stream.readByte();
for(int i = 0; i < amount; i++){
byte id = stream.readByte();
float time = stream.readFloat();
StatusEntry entry = Pools.obtain(StatusEntry.class, StatusEntry::new);
entry.set(content.getByID(ContentType.status, id), time);
statuses.add(entry);
}
}
}
@BaseComponent
class EntityComp{
int id;
void init(){}
void update(){}
void remove(){}
<T> T as(Class<T> type){
return (T)this;
}
}
}

View File

@ -1,10 +0,0 @@
package mindustry.entities.def;
import mindustry.annotations.Annotations.*;
import mindustry.entities.def.EntityComps.*;
class EntityDefs{
@EntityDef({BulletComp.class, VelComp.class, TimedComp.class})
class BulletDef{}
}

View File

@ -100,6 +100,8 @@ public class MusicControl{
/** Plays and fades in a music track. This must be called every frame.
* If something is already playing, fades out that track and fades in this new music.*/
private void play(@Nullable Music music){
if(!shouldPlay()) return;
//update volume of current track
if(current != null){
current.setVolume(fade * Core.settings.getInt("musicvol") / 100f);
@ -143,7 +145,7 @@ public class MusicControl{
/** Plays a music track once and only once. If something is already playing, does nothing.*/
private void playOnce(Music music){
if(current != null || music == null) return; //do not interrupt already-playing tracks
if(current != null || music == null || !shouldPlay()) return; //do not interrupt already-playing tracks
//save last random track played to prevent duplicates
lastRandomPlayed = music;
@ -162,6 +164,10 @@ public class MusicControl{
current.play();
}
private boolean shouldPlay(){
return Core.settings.getInt("musicvol") > 0;
}
/** Fades out the current track, unless it has already been silenced. */
private void silence(){
play(null);

View File

@ -375,7 +375,7 @@ public class Schematics implements Loadable{
/** Loads a schematic from base64. May throw an exception. */
public static Schematic readBase64(String schematic){
try{
return read(new ByteArrayInputStream(Base64Coder.decode(schematic)));
return read(new ByteArrayInputStream(Base64Coder.decode(schematic.trim())));
}catch(IOException e){
throw new RuntimeException(e);
}

View File

@ -611,7 +611,7 @@ public class Mods implements Loadable{
Fi metaf = zip.child("mod.json").exists() ? zip.child("mod.json") : zip.child("mod.hjson").exists() ? zip.child("mod.hjson") : zip.child("plugin.json");
if(!metaf.exists()){
Log.warn("Mod {0} doesn't have a 'mod.json'/'plugin.json'/'mod.js' file, skipping.", sourceFile);
Log.warn("Mod {0} doesn't have a 'mod.json'/'mod.hjson'/'plugin.json' file, skipping.", sourceFile);
throw new IllegalArgumentException("No mod.json found.");
}

View File

@ -44,7 +44,7 @@ public class ItemsDisplay extends Table{
t.setText(state.is(State.menu) ? "$launcheditems" : "$launchinfo");
t.setChecked(col.isCollapsed());
((Image)t.getChildren().get(1)).setDrawable(col.isCollapsed() ? Icon.upOpen : Icon.downOpen);
}).padBottom(4).left().fillX().margin(12f);
}).padBottom(4).left().fillX().margin(12f).minWidth(200f);
c.row();
c.add(col);
});

View File

@ -24,7 +24,6 @@ public class Junction extends Block{
super(name);
update = true;
solid = true;
instantTransfer = true;
group = BlockGroup.transportation;
unloadable = false;
entityType = JunctionEntity::new;

View File

@ -39,7 +39,6 @@ public class LiquidExtendingBridge extends ExtendingItemBridge{
}
if(entity.uptime >= 0.5f){
if(tryMoveLiquid(tile, other, false, entity.liquids.current()) > 0.1f){
entity.cycleSpeed = Mathf.lerpDelta(entity.cycleSpeed, 4f, 0.05f);
}else{

View File

@ -139,7 +139,7 @@ public class GenericCrafter extends Block{
if(outputItem != null && tile.entity.items.get(outputItem.item) >= itemCapacity){
return false;
}
return outputLiquid == null || !(tile.entity.liquids.get(outputLiquid.liquid) >= liquidCapacity);
return outputLiquid == null || !(tile.entity.liquids.get(outputLiquid.liquid) >= liquidCapacity - 0.001f);
}
@Override

View File

@ -1,3 +1,3 @@
org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m
archash=a57e709113a364ff718821de4c40366e17353329
archash=b2996f736d5b6870913f5d8b5496fe6033069ac8