Merge branch 'master' into crater
# Conflicts: # core/assets/sprites/block_colors.png # core/assets/sprites/sprites.atlas # core/assets/sprites/sprites.png # core/assets/sprites/sprites3.png # core/assets/sprites/sprites5.png # core/src/mindustry/world/modules/ItemModule.java
This commit is contained in:
@@ -33,6 +33,8 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
|
||||
|
||||
@Override
|
||||
public void setup(){
|
||||
Events.fire(new ClientCreateEvent());
|
||||
|
||||
Vars.loadLogger();
|
||||
Vars.loadFileLogger();
|
||||
Vars.platform = this;
|
||||
|
||||
@@ -1129,13 +1129,13 @@ public class Blocks implements ContentList{
|
||||
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));
|
||||
powerProduction = 16f;
|
||||
itemDuration = 120f;
|
||||
itemDuration = 140f;
|
||||
hasLiquids = true;
|
||||
hasItems = true;
|
||||
size = 3;
|
||||
|
||||
consumes.item(Items.pyratite).optional(true, false);
|
||||
consumes.liquid(Liquids.cryofluid, 0.18f);
|
||||
consumes.liquid(Liquids.cryofluid, 0.15f);
|
||||
}};
|
||||
|
||||
rtgGenerator = new DecayGenerator("rtg-generator"){{
|
||||
|
||||
@@ -3,12 +3,12 @@ package mindustry.core;
|
||||
import arc.*;
|
||||
import arc.assets.*;
|
||||
import arc.audio.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.input.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.GameState.*;
|
||||
@@ -114,17 +114,17 @@ public class Control implements ApplicationListener, Loadable{
|
||||
});
|
||||
|
||||
//autohost for pvp maps
|
||||
Events.on(WorldLoadEvent.class, event -> {
|
||||
Events.on(WorldLoadEvent.class, event -> app.post(() -> {
|
||||
if(state.rules.pvp && !net.active()){
|
||||
try{
|
||||
net.host(port);
|
||||
player.isAdmin = true;
|
||||
}catch(IOException e){
|
||||
ui.showException("$server.error", e);
|
||||
Core.app.post(() -> state.set(State.menu));
|
||||
state.set(State.menu);
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
Events.on(UnlockEvent.class, e -> ui.hudfrag.showUnlock(e.content));
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.BuildBlock.*;
|
||||
import mindustry.world.blocks.power.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -246,7 +245,6 @@ public class Logic implements ApplicationListener{
|
||||
collisions.updatePhysics(unitGroup);
|
||||
}
|
||||
|
||||
|
||||
playerGroup.update();
|
||||
|
||||
//effect group only contains item transfers in the headless version, update it!
|
||||
|
||||
@@ -13,6 +13,7 @@ import mindustry.annotations.Annotations.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
@@ -101,6 +102,7 @@ public class NetClient implements ApplicationListener{
|
||||
state.set(State.menu);
|
||||
logic.reset();
|
||||
platform.updateRPC();
|
||||
player.name = Core.settings.getString("name");
|
||||
|
||||
if(quiet) return;
|
||||
|
||||
@@ -261,36 +263,61 @@ public class NetClient implements ApplicationListener{
|
||||
ui.loadfrag.hide();
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both, unreliable = true)
|
||||
public static void setHudText(String message){
|
||||
if(message == null) return;
|
||||
|
||||
ui.hudfrag.setHudText(message);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void hideHudText(){
|
||||
ui.hudfrag.toggleHudText(false);
|
||||
}
|
||||
|
||||
/** TCP version */
|
||||
@Remote(variants = Variant.both)
|
||||
public static void setHudTextReliable(String message){
|
||||
setHudText(message);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onInfoMessage(String message){
|
||||
if(message == null) return;
|
||||
|
||||
ui.showText("", message);
|
||||
}
|
||||
|
||||
//TODO these are commented out to enforce compatibility with 103! uncomment before 104 release
|
||||
/*
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onInfoPopup(String message, float duration, int align, int top, int left, int bottom, int right){
|
||||
if(message == null) return;
|
||||
|
||||
ui.showInfoPopup(message, duration, align, top, left, bottom, right);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onLabel(String info, float duration, float worldx, float worldy){
|
||||
ui.showLabel(info, duration, worldx, worldy);
|
||||
public static void onLabel(String message, float duration, float worldx, float worldy){
|
||||
if(message == null) return;
|
||||
|
||||
ui.showLabel(message, duration, worldx, worldy);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both, unreliable = true)
|
||||
public static void onEffect(Effect effect, float x, float y, float rotation, Color color){
|
||||
if(effect == null) return;
|
||||
|
||||
Effects.effect(effect, color, x, y, rotation);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onEffectReliable(Effect effect, float x, float y, float rotation, Color color){
|
||||
Effects.effect(effect, color, x, y, rotation);
|
||||
}*/
|
||||
onEffect(effect, x, y, rotation, color);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onInfoToast(String message, float duration){
|
||||
if(message == null) return;
|
||||
|
||||
ui.showInfoToast(message, duration);
|
||||
}
|
||||
|
||||
@@ -541,6 +568,11 @@ public class NetClient implements ApplicationListener{
|
||||
}
|
||||
|
||||
String getUsid(String ip){
|
||||
//consistently use the latter part of an IP, if possible
|
||||
if(ip.contains("/")){
|
||||
ip = ip.substring(ip.indexOf("/") + 1);
|
||||
}
|
||||
|
||||
if(Core.settings.getString("usid-" + ip, null) != null){
|
||||
return Core.settings.getString("usid-" + ip, null);
|
||||
}else{
|
||||
|
||||
@@ -8,6 +8,7 @@ import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.CommandHandler.*;
|
||||
import arc.util.io.*;
|
||||
import arc.util.serialization.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.GameState.*;
|
||||
@@ -15,7 +16,6 @@ import mindustry.entities.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.net.Administration;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Teams.*;
|
||||
@@ -48,6 +48,8 @@ public class NetServer implements ApplicationListener{
|
||||
if(state.rules.pvp){
|
||||
//find team with minimum amount of players and auto-assign player to that.
|
||||
TeamData re = state.teams.getActive().min(data -> {
|
||||
if((state.rules.waveTeam == data.team && state.rules.waves) || !data.team.active()) return Integer.MAX_VALUE;
|
||||
|
||||
int count = 0;
|
||||
for(Player other : players){
|
||||
if(other.getTeam() == data.team && other != player){
|
||||
@@ -93,6 +95,16 @@ public class NetServer implements ApplicationListener{
|
||||
}
|
||||
|
||||
String uuid = packet.uuid;
|
||||
byte[] buuid = Base64Coder.decode(uuid);
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(buuid, 0, 8);
|
||||
ByteBuffer buff = ByteBuffer.allocate(8);
|
||||
buff.put(buuid, 8, 8);
|
||||
buff.position(0);
|
||||
if(crc.getValue() != buff.getLong()){
|
||||
con.kick(KickReason.clientOutdated);
|
||||
return;
|
||||
}
|
||||
|
||||
if(admins.isIPBanned(con.address) || admins.isSubnetBanned(con.address)) return;
|
||||
|
||||
@@ -121,7 +133,7 @@ public class NetServer implements ApplicationListener{
|
||||
return;
|
||||
}
|
||||
|
||||
if(admins.getPlayerLimit() > 0 && playerGroup.size() >= admins.getPlayerLimit()){
|
||||
if(admins.getPlayerLimit() > 0 && playerGroup.size() >= admins.getPlayerLimit() && !netServer.admins.isAdmin(uuid, packet.usid)){
|
||||
con.kick(KickReason.playerLimit);
|
||||
return;
|
||||
}
|
||||
@@ -207,6 +219,11 @@ public class NetServer implements ApplicationListener{
|
||||
player.color.set(packet.color);
|
||||
player.color.a = 1f;
|
||||
|
||||
//save admin ID but don't overwrite it
|
||||
if(!player.isAdmin && !info.admin){
|
||||
info.adminUsid = packet.usid;
|
||||
}
|
||||
|
||||
try{
|
||||
writeBuffer.position(0);
|
||||
player.write(outputBuffer);
|
||||
@@ -313,7 +330,7 @@ public class NetServer implements ApplicationListener{
|
||||
votes += d;
|
||||
voted.addAll(player.uuid, admins.getInfo(player.uuid).lastIP);
|
||||
|
||||
Call.sendMessage(Strings.format("[orange]{0}[lightgray] has voted to kick[orange] {1}[].[accent] ({2}/{3})\n[lightgray]Type[orange] /vote <y/n>[] to agree.",
|
||||
Call.sendMessage(Strings.format("[orange]{0}[lightgray] has voted on kicking[orange] {1}[].[accent] ({2}/{3})\n[lightgray]Type[orange] /vote <y/n>[] to agree.",
|
||||
player.name, target.name, votes, votesRequired()));
|
||||
}
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ public class Renderer implements ApplicationListener{
|
||||
drawAllTeams(true);
|
||||
|
||||
Draw.flush();
|
||||
if(bloom != null && !pixelator.enabled()){
|
||||
if(bloom != null){
|
||||
bloom.capture();
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ public class Renderer implements ApplicationListener{
|
||||
effectGroup.draw();
|
||||
|
||||
Draw.flush();
|
||||
if(bloom != null && !pixelator.enabled()){
|
||||
if(bloom != null){
|
||||
bloom.render();
|
||||
}
|
||||
|
||||
@@ -417,11 +417,6 @@ public class Renderer implements ApplicationListener{
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hadShields = Core.settings.getBool("animatedshields");
|
||||
boolean hadWater = Core.settings.getBool("animatedwater");
|
||||
Core.settings.put("animatedwater", false);
|
||||
Core.settings.put("animatedshields", false);
|
||||
|
||||
FrameBuffer buffer = new FrameBuffer(w, h);
|
||||
|
||||
float vpW = camera.width, vpH = camera.height, px = camera.position.x, py = camera.position.y;
|
||||
@@ -446,16 +441,13 @@ public class Renderer implements ApplicationListener{
|
||||
}
|
||||
buffer.end();
|
||||
Pixmap fullPixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888);
|
||||
BufferUtils.copy(lines, 0, fullPixmap.getPixels(), lines.length);
|
||||
Buffers.copy(lines, 0, fullPixmap.getPixels(), lines.length);
|
||||
Fi file = screenshotDirectory.child("screenshot-" + Time.millis() + ".png");
|
||||
PixmapIO.writePNG(file, fullPixmap);
|
||||
fullPixmap.dispose();
|
||||
ui.showInfoFade(Core.bundle.format("screenshot", file.toString()));
|
||||
|
||||
buffer.dispose();
|
||||
|
||||
Core.settings.put("animatedwater", hadWater);
|
||||
Core.settings.put("animatedshields", hadShields);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ public class Units{
|
||||
* Validates a target.
|
||||
* @param target The target to validate
|
||||
* @param team The team of the thing doing tha targeting
|
||||
* @param x The X position of the thing doign the targeting
|
||||
* @param y The Y position of the thing doign the targeting
|
||||
* @param x The X position of the thing doing the targeting
|
||||
* @param y The Y position of the thing doing the targeting
|
||||
* @param range The maximum distance from the target X/Y the targeter can be for it to be valid
|
||||
* @return whether the target is invalid
|
||||
*/
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package mindustry.entities.traits;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.Queue;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.Queue;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -21,7 +22,7 @@ import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.entities.traits.BuilderTrait.BuildDataStatic.*;
|
||||
import static mindustry.entities.traits.BuilderTrait.BuildDataStatic.tmptr;
|
||||
|
||||
/** Interface for units that build things.*/
|
||||
public interface BuilderTrait extends Entity, TeamTrait{
|
||||
@@ -74,6 +75,9 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
buildQueue().removeFirst();
|
||||
return;
|
||||
}
|
||||
}else if(tile.getTeam() != getTeam()){
|
||||
buildQueue().removeFirst();
|
||||
return;
|
||||
}
|
||||
|
||||
if(tile.entity instanceof BuildEntity && !current.initialized){
|
||||
|
||||
@@ -92,6 +92,10 @@ public class EventType{
|
||||
}
|
||||
}
|
||||
|
||||
public static class ClientCreateEvent{
|
||||
|
||||
}
|
||||
|
||||
/** Called when the client game is first loaded. */
|
||||
public static class ClientLoadEvent{
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public class GlobalData{
|
||||
for(Fi add : files){
|
||||
if(add.isDirectory()) continue;
|
||||
zos.putNextEntry(new ZipEntry(add.path().substring(base.length())));
|
||||
Streams.copyStream(add.read(), zos);
|
||||
Streams.copy(add.read(), zos);
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,9 @@ public class Rules{
|
||||
public boolean lighting = false;
|
||||
/** Ambient light color, used when lighting is enabled. */
|
||||
public Color ambientLight = new Color(0.01f, 0.01f, 0.04f, 0.99f);
|
||||
/** Multiplier for solar panel power output.
|
||||
negative = use ambient light if lighting is enabled. */
|
||||
public float solarPowerMultiplier = -1f;
|
||||
/** team of the player by default */
|
||||
public Team defaultTeam = Team.sharded;
|
||||
/** team of the enemy in waves/sectors */
|
||||
|
||||
@@ -98,6 +98,7 @@ public class Teams{
|
||||
|
||||
/** Do not modify. */
|
||||
public Array<TeamData> getActive(){
|
||||
active.removeAll(t -> !t.active());
|
||||
return active;
|
||||
}
|
||||
|
||||
@@ -167,6 +168,14 @@ public class Teams{
|
||||
public CoreEntity core(){
|
||||
return cores.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "TeamData{" +
|
||||
"cores=" + cores +
|
||||
", team=" + team +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
/** Represents a block made by this team that was destroyed somewhere on the map.
|
||||
|
||||
@@ -168,7 +168,6 @@ public class BlockRenderer implements Disposable{
|
||||
shadowEvents.clear();
|
||||
|
||||
Draw.proj(camera.projection());
|
||||
renderer.pixelator.rebind();
|
||||
}
|
||||
|
||||
float ww = world.width() * tilesize, wh = world.height() * tilesize;
|
||||
|
||||
@@ -24,6 +24,10 @@ public class LightRenderer{
|
||||
lights.add(run);
|
||||
}
|
||||
|
||||
public void add(Position pos, float radius, Color color, float opacity){
|
||||
add(pos.getX(), pos.getY(), radius, color, opacity);
|
||||
}
|
||||
|
||||
public void add(float x, float y, float radius, Color color, float opacity){
|
||||
if(!enabled()) return;
|
||||
|
||||
@@ -180,13 +184,14 @@ public class LightRenderer{
|
||||
|
||||
Draw.color();
|
||||
buffer.beginDraw(Color.clear);
|
||||
Draw.blend(Blending.normal);
|
||||
Gl.blendEquationSeparate(Gl.funcAdd, Gl.max);
|
||||
|
||||
for(Runnable run : lights){
|
||||
run.run();
|
||||
}
|
||||
Draw.reset();
|
||||
Draw.blend();
|
||||
buffer.endDraw();
|
||||
Gl.blendEquationSeparate(Gl.funcAdd, Gl.funcAdd);
|
||||
|
||||
Draw.color();
|
||||
Shaders.light.ambient.set(state.rules.ambientLight);
|
||||
@@ -196,4 +201,4 @@ public class LightRenderer{
|
||||
|
||||
lights.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,6 @@ public class Pixelator implements Disposable{
|
||||
camera.width = (int)camera.width;
|
||||
camera.height = (int)camera.height;
|
||||
|
||||
boolean hadShields = Core.settings.getBool("animatedshields");
|
||||
boolean hadWater = Core.settings.getBool("animatedwater");
|
||||
Core.settings.put("animatedwater", false);
|
||||
Core.settings.put("animatedshields", false);
|
||||
graphics.clear(0f, 0f, 0f, 1f);
|
||||
|
||||
float px = Core.camera.position.x, py = Core.camera.position.y;
|
||||
@@ -58,17 +54,9 @@ public class Pixelator implements Disposable{
|
||||
playerGroup.draw(p -> !p.isDead(), Player::drawName);
|
||||
|
||||
Core.camera.position.set(px, py);
|
||||
Core.settings.put("animatedwater", hadWater);
|
||||
Core.settings.put("animatedshields", hadShields);
|
||||
renderer.setScale(pre);
|
||||
}
|
||||
|
||||
public void rebind(){
|
||||
if(enabled()){
|
||||
buffer.begin();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean enabled(){
|
||||
return Core.settings.getBool("pixelate");
|
||||
}
|
||||
|
||||
@@ -255,19 +255,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
if(lastSchematic == null) return;
|
||||
|
||||
ui.showTextInput("$schematic.add", "$name", "", text -> {
|
||||
Schematic replacement = schematics.all().find(s -> s.name().equals(text));
|
||||
if(replacement != null){
|
||||
ui.showConfirm("$confirm", "$schematic.replace", () -> {
|
||||
schematics.overwrite(replacement, lastSchematic);
|
||||
ui.showInfoFade("$schematic.saved");
|
||||
ui.schematics.showInfo(replacement);
|
||||
});
|
||||
}else{
|
||||
lastSchematic.tags.put("name", text);
|
||||
schematics.add(lastSchematic);
|
||||
ui.showInfoFade("$schematic.saved");
|
||||
ui.schematics.showInfo(lastSchematic);
|
||||
}
|
||||
lastSchematic.tags.put("name", text);
|
||||
schematics.add(lastSchematic);
|
||||
ui.showInfoFade("$schematic.saved");
|
||||
ui.schematics.showInfo(lastSchematic);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package mindustry.mod;
|
||||
import arc.*;
|
||||
import arc.assets.*;
|
||||
import arc.audio.*;
|
||||
import arc.audio.mock.*;
|
||||
import arc.mock.*;
|
||||
import arc.struct.Array;
|
||||
import arc.struct.*;
|
||||
import arc.files.*;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package mindustry.mod;
|
||||
|
||||
import arc.audio.*;
|
||||
import arc.audio.mock.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.mock.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
|
||||
public class ModLoadingSound implements Sound{
|
||||
|
||||
@@ -118,7 +118,7 @@ public class Mods implements Loadable{
|
||||
private void packSprites(Array<Fi> sprites, LoadedMod mod, boolean prefix){
|
||||
for(Fi file : sprites){
|
||||
try(InputStream stream = file.read()){
|
||||
byte[] bytes = Streams.copyStreamToByteArray(stream, Math.max((int)file.length(), 512));
|
||||
byte[] bytes = Streams.copyBytes(stream, Math.max((int)file.length(), 512));
|
||||
Pixmap pixmap = new Pixmap(bytes, 0, bytes.length);
|
||||
packer.add(getPage(file), (prefix ? mod.name + "-" : "") + file.nameWithoutExtension(), new PixmapRegion(pixmap));
|
||||
pixmap.dispose();
|
||||
@@ -317,7 +317,7 @@ public class Mods implements Loadable{
|
||||
return result;
|
||||
}
|
||||
|
||||
private LoadedMod locateMod(String name){
|
||||
public LoadedMod locateMod(String name){
|
||||
return mods.find(mod -> mod.enabled() && mod.name.equals(name));
|
||||
}
|
||||
|
||||
@@ -460,22 +460,25 @@ public class Mods implements Loadable{
|
||||
eachEnabled(mod -> {
|
||||
if(mod.root.child("scripts").exists()){
|
||||
content.setCurrentMod(mod);
|
||||
mod.scripts = mod.root.child("scripts").findAll(f -> f.extension().equals("js"));
|
||||
Log.debug("[{0}] Found {1} scripts.", mod.meta.name, mod.scripts.size);
|
||||
|
||||
for(Fi file : mod.scripts){
|
||||
//if there's only one script file, use it (for backwards compatibility); if there isn't, use "main.js"
|
||||
Array<Fi> allScripts = mod.root.child("scripts").findAll(f -> f.extEquals("js"));
|
||||
Fi main = allScripts.size == 1 ? allScripts.first() : mod.root.child("scripts").child("main.js");
|
||||
if(main.exists() && !main.isDirectory()){
|
||||
try{
|
||||
if(scripts == null){
|
||||
scripts = platform.createScripts();
|
||||
}
|
||||
scripts.run(mod, file);
|
||||
scripts.run(mod, main);
|
||||
}catch(Throwable e){
|
||||
Core.app.post(() -> {
|
||||
Log.err("Error loading script {0} for mod {1}.", file.name(), mod.meta.name);
|
||||
Log.err("Error loading main script {0} for mod {1}.", main.name(), mod.meta.name);
|
||||
e.printStackTrace();
|
||||
});
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
Core.app.post(() -> {
|
||||
Log.err("No main.js found for mod {0}.", mod.meta.name);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,6 +8,12 @@ import arc.util.Log.*;
|
||||
import mindustry.*;
|
||||
import mindustry.mod.Mods.*;
|
||||
import org.mozilla.javascript.*;
|
||||
import org.mozilla.javascript.commonjs.module.*;
|
||||
import org.mozilla.javascript.commonjs.module.provider.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.regex.*;
|
||||
|
||||
public class Scripts implements Disposable{
|
||||
private final Array<String> blacklist = Array.with("net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk",
|
||||
@@ -15,9 +21,9 @@ public class Scripts implements Disposable{
|
||||
".awt", "socket", "classloader", "oracle", "invoke");
|
||||
private final Array<String> whitelist = Array.with("mindustry.net");
|
||||
private final Context context;
|
||||
private final String wrapper;
|
||||
private Scriptable scope;
|
||||
private boolean errored;
|
||||
private LoadedMod currentMod = null;
|
||||
|
||||
public Scripts(){
|
||||
Time.mark();
|
||||
@@ -25,9 +31,12 @@ public class Scripts implements Disposable{
|
||||
context = Vars.platform.getScriptContext();
|
||||
context.setClassShutter(type -> !blacklist.contains(type.toLowerCase()::contains) || whitelist.contains(type.toLowerCase()::contains));
|
||||
context.getWrapFactory().setJavaPrimitiveWrap(false);
|
||||
|
||||
|
||||
scope = new ImporterTopLevel(context);
|
||||
wrapper = Core.files.internal("scripts/wrapper.js").readString();
|
||||
|
||||
new RequireBuilder()
|
||||
.setModuleScriptProvider(new SoftCachingModuleScriptProvider(new ScriptModuleProvider()))
|
||||
.setSandboxed(true).createRequire(context, scope).install(scope);
|
||||
|
||||
if(!run(Core.files.internal("scripts/global.js").readString(), "global.js")){
|
||||
errored = true;
|
||||
@@ -68,11 +77,17 @@ public class Scripts implements Disposable{
|
||||
}
|
||||
|
||||
public void run(LoadedMod mod, Fi file){
|
||||
run(wrapper.replace("$SCRIPT_NAME$", mod.name + "/" + file.nameWithoutExtension()).replace("$CODE$", file.readString()).replace("$MOD_NAME$", mod.name), file.name());
|
||||
currentMod = mod;
|
||||
run(file.readString(), file.name());
|
||||
currentMod = null;
|
||||
}
|
||||
|
||||
private boolean run(String script, String file){
|
||||
try{
|
||||
if(currentMod != null){
|
||||
//inject script info into file (TODO maybe rhino handles this?)
|
||||
context.evaluateString(scope, "modName = \"" + currentMod.name + "\"\nscriptName = \"" + file + "\"", "initscript.js", 1, null);
|
||||
}
|
||||
context.evaluateString(scope, script, file, 1, null);
|
||||
return true;
|
||||
}catch(Throwable t){
|
||||
@@ -85,4 +100,38 @@ public class Scripts implements Disposable{
|
||||
public void dispose(){
|
||||
Context.exit();
|
||||
}
|
||||
|
||||
private class ScriptModuleProvider extends UrlModuleSourceProvider{
|
||||
private Pattern directory = Pattern.compile("^(.+?)/(.+)");
|
||||
|
||||
public ScriptModuleProvider(){
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleSource loadSource(String moduleId, Scriptable paths, Object validator) throws IOException, URISyntaxException{
|
||||
if(currentMod == null) return null;
|
||||
return loadSource(moduleId, currentMod.root.child("scripts"), validator);
|
||||
}
|
||||
|
||||
private ModuleSource loadSource(String moduleId, Fi root, Object validator) throws URISyntaxException{
|
||||
Matcher matched = directory.matcher(moduleId);
|
||||
if(matched.find()){
|
||||
LoadedMod required = Vars.mods.locateMod(matched.group(1));
|
||||
String script = matched.group(2);
|
||||
if(required == null || root.equals(required.root.child("scripts"))){ // Mod not found, or already using a mod
|
||||
Fi dir = root.child(matched.group(1));
|
||||
if(!dir.exists()) return null; // Mod and folder not found
|
||||
return loadSource(script, dir, validator);
|
||||
}
|
||||
return loadSource(script, required.root.child("scripts"), validator);
|
||||
}
|
||||
|
||||
Fi module = root.child(moduleId + ".js");
|
||||
if(!module.exists() || module.isDirectory()) return null;
|
||||
return new ModuleSource(
|
||||
new InputStreamReader(new ByteArrayInputStream((module.readString()).getBytes())),
|
||||
null, new URI(moduleId), root.file().toURI(), validator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ public class Administration{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all players with admin status
|
||||
* Returns list of all players which are banned
|
||||
*/
|
||||
public Array<PlayerInfo> getBanned(){
|
||||
Array<PlayerInfo> result = new Array<>();
|
||||
@@ -568,6 +568,7 @@ public class Administration{
|
||||
player = null;
|
||||
type = null;
|
||||
tile = null;
|
||||
block = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ public class Packets{
|
||||
usid = TypeIO.readString(buffer);
|
||||
mobile = buffer.get() == 1;
|
||||
color = buffer.getInt();
|
||||
byte[] idbytes = new byte[8];
|
||||
byte[] idbytes = new byte[16];
|
||||
buffer.get(idbytes);
|
||||
uuid = new String(Base64Coder.encode(idbytes));
|
||||
int totalMods = buffer.get();
|
||||
|
||||
@@ -16,7 +16,7 @@ public class Links{
|
||||
new LinkEntry("changelog", "https://github.com/Anuken/Mindustry/releases", Icon.list, Pal.accent.cpy()),
|
||||
new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Icon.trello, Color.valueOf("026aa7")),
|
||||
new LinkEntry("wiki", "https://mindustrygame.github.io/wiki/", Icon.book, Color.valueOf("0f142f")),
|
||||
new LinkEntry("feathub", "https://feathub.com/Anuken/Mindustry/", Icon.add, Color.valueOf("ebebeb")),
|
||||
new LinkEntry("feathub", "https://github.com/Anuken/Mindustry-Suggestions/issues/new/choose/", Icon.add, Color.valueOf("ebebeb")),
|
||||
new LinkEntry("reddit", "https://www.reddit.com/r/Mindustry/", Icon.redditAlien, Color.valueOf("ee593b")),
|
||||
new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Icon.itchio, Color.valueOf("fa5c5c")),
|
||||
new LinkEntry("google-play", "https://play.google.com/store/apps/details?id=io.anuke.mindustry", Icon.googleplay, Color.valueOf("689f38")),
|
||||
|
||||
@@ -73,7 +73,6 @@ public class CustomGameDialog extends FloatingDialog{
|
||||
image.row();
|
||||
image.add(img).size(images);
|
||||
|
||||
|
||||
BorderImage border = new BorderImage(map.safeTexture(), 3f);
|
||||
border.setScaling(Scaling.fit);
|
||||
image.replaceImage(border);
|
||||
|
||||
@@ -172,6 +172,7 @@ public class CustomRulesDialog extends FloatingDialog{
|
||||
number("$rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200));
|
||||
|
||||
title("$rules.title.experimental");
|
||||
number("$rules.solarpowermultiplier", f -> rules.solarPowerMultiplier = f, () -> rules.solarPowerMultiplier);
|
||||
check("$rules.lighting", b -> rules.lighting = b, () -> rules.lighting);
|
||||
|
||||
main.addButton(b -> {
|
||||
|
||||
@@ -242,6 +242,9 @@ public class JoinDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
void setup(){
|
||||
local.clear();
|
||||
remote.clear();
|
||||
global.clear();
|
||||
float w = targetWidth();
|
||||
|
||||
hosts.clear();
|
||||
@@ -255,7 +258,6 @@ public class JoinDialog extends FloatingDialog{
|
||||
pane.setScrollingDisabled(true, false);
|
||||
|
||||
setupRemote();
|
||||
refreshRemote();
|
||||
|
||||
cont.clear();
|
||||
cont.table(t -> {
|
||||
|
||||
@@ -40,7 +40,7 @@ public class ModsDialog extends FloatingDialog{
|
||||
}else{
|
||||
try{
|
||||
Fi file = tmpDirectory.child(text.replace("/", "") + ".zip");
|
||||
Streams.copyStream(result.getResultAsStream(), file.write(false));
|
||||
Streams.copy(result.getResultAsStream(), file.write(false));
|
||||
mods.importMod(file);
|
||||
file.delete();
|
||||
Core.app.post(() -> {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.files.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.graphics.g2d.*;
|
||||
@@ -10,6 +10,7 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.ImageButton.*;
|
||||
import arc.scene.ui.TextButton.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.game.*;
|
||||
@@ -214,14 +215,27 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
Core.app.setClipboardText(schematics.writeBase64(s));
|
||||
}).marginLeft(12f);
|
||||
t.row();
|
||||
t.addImageTextButton("$schematic.exportfile", Icon.export, style, () -> platform.showFileChooser(false, schematicExtension, file -> {
|
||||
dialog.hide();
|
||||
try{
|
||||
Schematics.write(s, file);
|
||||
}catch(Exception e){
|
||||
ui.showException(e);
|
||||
t.addImageTextButton("$schematic.exportfile", Icon.export, style, () -> {
|
||||
if(!ios){
|
||||
platform.showFileChooser(false, schematicExtension, file -> {
|
||||
dialog.hide();
|
||||
try{
|
||||
Schematics.write(s, file);
|
||||
}catch(Throwable e){
|
||||
ui.showException(e);
|
||||
}
|
||||
});
|
||||
}else{
|
||||
dialog.hide();
|
||||
try{
|
||||
Fi file = Core.files.local(s.name() + "." + schematicExtension);
|
||||
Schematics.write(s, file);
|
||||
platform.shareFile(file);
|
||||
}catch(Throwable e){
|
||||
ui.showException(e);
|
||||
}
|
||||
}
|
||||
})).marginLeft(12f);
|
||||
}).marginLeft(12f);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -330,7 +330,12 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
if(Shaders.shield != null){
|
||||
graphics.checkPref("animatedshields", !mobile);
|
||||
}
|
||||
graphics.checkPref("bloom", !mobile, val -> renderer.toggleBloom(val));
|
||||
if(!ios){
|
||||
graphics.checkPref("bloom", !mobile, val -> renderer.toggleBloom(val));
|
||||
}else{
|
||||
Core.settings.put("bloom", false);
|
||||
}
|
||||
|
||||
graphics.checkPref("pixelate", false, val -> {
|
||||
if(val){
|
||||
Events.fire(Trigger.enablePixelation);
|
||||
|
||||
@@ -231,6 +231,8 @@ public class ChatFragment extends Table{
|
||||
|
||||
fadetime += 1f;
|
||||
fadetime = Math.min(fadetime, messagesShown) + 1f;
|
||||
|
||||
if(scrollPos > 0) scrollPos++;
|
||||
}
|
||||
|
||||
private static class ChatMessage{
|
||||
|
||||
@@ -43,6 +43,9 @@ public class HudFragment extends Fragment{
|
||||
private boolean shown = true;
|
||||
private float dsize = 47.2f;
|
||||
|
||||
private String hudText = "";
|
||||
private boolean showHudText;
|
||||
|
||||
private long lastToast;
|
||||
|
||||
public void build(Group parent){
|
||||
@@ -341,6 +344,19 @@ public class HudFragment extends Fragment{
|
||||
t.add("$saveload").style(Styles.outlineLabel);
|
||||
});
|
||||
|
||||
parent.fill(p -> {
|
||||
p.top().table(Styles.black3, t -> t.margin(4).label(() -> hudText)
|
||||
.style(Styles.outlineLabel)).padTop(10).visible(p.color.a >= 0.001f);
|
||||
p.update(() -> {
|
||||
p.color.a = Mathf.lerpDelta(p.color.a, Mathf.num(showHudText), 0.2f);
|
||||
if(state.is(State.menu)){
|
||||
p.color.a = 0f;
|
||||
showHudText = false;
|
||||
}
|
||||
});
|
||||
p.touchable(Touchable.disabled);
|
||||
});
|
||||
|
||||
blockfrag.build(parent);
|
||||
}
|
||||
|
||||
@@ -368,6 +384,15 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
}
|
||||
|
||||
public void setHudText(String text){
|
||||
showHudText = true;
|
||||
hudText = text;
|
||||
}
|
||||
|
||||
public void toggleHudText(boolean shown){
|
||||
showHudText = shown;
|
||||
}
|
||||
|
||||
private void scheduleToast(Runnable run){
|
||||
long duration = (int)(3.5 * 1000);
|
||||
long since = Time.timeSinceMillis(lastToast);
|
||||
|
||||
@@ -84,7 +84,7 @@ public interface Autotiler{
|
||||
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());
|
||||
return other != null && other.getTeam() == tile.getTeam() && blends(tile, rotation, other.x, other.y, other.rotation(), other.block());
|
||||
}
|
||||
|
||||
default boolean blendsArmored(Tile tile, int rotation, int otherx, int othery, int otherrot, Block otherblock){
|
||||
|
||||
@@ -1,31 +1,29 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import arc.struct.*;
|
||||
import arc.func.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ItemSelection{
|
||||
private static float scrollPos = 0f;
|
||||
|
||||
public static void buildItemTable(Table table, Prov<Item> holder, Cons<Item> consumer){
|
||||
|
||||
Array<Item> items = content.items();
|
||||
public static <T extends UnlockableContent> void buildTable(Table table, Array<T> items, Prov<T> holder, Cons<T> consumer){
|
||||
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
group.setMinCheckCount(0);
|
||||
Table cont = new Table();
|
||||
cont.defaults().size(38);
|
||||
cont.defaults().size(40);
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(Item item : items){
|
||||
for(T item : items){
|
||||
if(!data.isUnlocked(item) && world.isZone()) continue;
|
||||
|
||||
ImageButton button = cont.addImageButton(Tex.whiteui, Styles.clearToggleTransi, 24, () -> control.input.frag.config.hideConfig()).group(group).get();
|
||||
@@ -38,6 +36,22 @@ public class ItemSelection{
|
||||
}
|
||||
}
|
||||
|
||||
table.add(cont);
|
||||
//add extra blank spaces so it looks nice
|
||||
if(i % 4 != 0){
|
||||
int remaining = 4 - (i % 4);
|
||||
for(int j = 0; j < remaining; j++){
|
||||
cont.addImage(Styles.black6);
|
||||
}
|
||||
}
|
||||
|
||||
ScrollPane pane = new ScrollPane(cont, Styles.smallPane);
|
||||
pane.setScrollingDisabled(true, false);
|
||||
pane.setScrollYForce(scrollPos);
|
||||
pane.update(() -> {
|
||||
scrollPos = pane.getScrollY();
|
||||
});
|
||||
|
||||
pane.setOverscroll(false, false);
|
||||
table.add(pane).maxHeight(Scl.scl(40 * 5));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +266,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||
ConveyorEntity e = tile.ent();
|
||||
amount = Math.min(amount, itemCapacity - e.len);
|
||||
|
||||
for(int i = amount - 1; i >= 0; i--){
|
||||
e.add(0);
|
||||
|
||||
@@ -2,13 +2,15 @@ package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.math.Mathf;
|
||||
import arc.util.Time;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.type.Item;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.BlockGroup;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.world;
|
||||
|
||||
public class OverflowGate extends Block{
|
||||
public float speed = 1f;
|
||||
public boolean invert = false;
|
||||
@@ -28,6 +30,11 @@ public class OverflowGate extends Block{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeStack(Tile tile, Item item, int amount){
|
||||
OverflowGateEntity entity = tile.ent();
|
||||
@@ -47,6 +54,11 @@ public class OverflowGate extends Block{
|
||||
}
|
||||
|
||||
if(entity.lastItem != null){
|
||||
if(entity.lastInput == null){
|
||||
entity.lastItem = null;
|
||||
return;
|
||||
}
|
||||
|
||||
entity.time += 1f / speed * Time.delta();
|
||||
Tile target = getTileTarget(tile, entity.lastItem, entity.lastInput, false);
|
||||
|
||||
@@ -120,19 +132,24 @@ public class OverflowGate extends Block{
|
||||
|
||||
@Override
|
||||
public byte version(){
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeInt(lastInput == null ? Pos.invalid : lastInput.pos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
|
||||
if(revision == 1){
|
||||
new DirectionalItemBuffer(25, 50f).read(stream);
|
||||
}else if(revision == 3){
|
||||
lastInput = world.tile(stream.readInt());
|
||||
lastItem = items.first();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.content;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Sorter extends Block{
|
||||
private static Item lastItem;
|
||||
@@ -46,6 +46,9 @@ public class Sorter extends Block{
|
||||
@Override
|
||||
public void configured(Tile tile, Player player, int value){
|
||||
tile.<SorterEntity>ent().sortItem = content.item(value);
|
||||
if(!headless){
|
||||
renderer.minimap.update(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,7 +136,7 @@ public class Sorter extends Block{
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
SorterEntity entity = tile.ent();
|
||||
ItemSelection.buildItemTable(table, () -> entity.sortItem, item -> {
|
||||
ItemSelection.buildTable(table, content.items(), () -> entity.sortItem, item -> {
|
||||
lastItem = item;
|
||||
tile.configure(item == null ? -1 : item.id);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,29 @@
|
||||
package mindustry.world.blocks.power;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
|
||||
public class Battery extends PowerDistributor{
|
||||
public int topRegion = reg("-top");
|
||||
|
||||
public Color emptyLightColor = Color.valueOf("f8c266");
|
||||
public Color fullLightColor = Color.valueOf("fb9567");
|
||||
|
||||
public Battery(String name){
|
||||
super(name);
|
||||
outputsPower = true;
|
||||
consumesPower = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.color(emptyLightColor, fullLightColor, tile.entity.power.status);
|
||||
Fill.square(tile.drawx(), tile.drawy(), tilesize * size / 2f - 1);
|
||||
Draw.color();
|
||||
|
||||
Draw.rect(reg(topRegion), tile.drawx(), tile.drawy());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class SolarGenerator extends PowerGenerator{
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
tile.<GeneratorEntity>ent().productionEfficiency = state.rules.lighting ? 1f - state.rules.ambientLight.a : 1f;
|
||||
tile.<GeneratorEntity>ent().productionEfficiency = state.rules.solarPowerMultiplier < 0 ? (state.rules.lighting ? 1f - state.rules.ambientLight.a : 1f) : state.rules.solarPowerMultiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -107,6 +107,7 @@ public class Separator extends Block{
|
||||
entity.cons.trigger();
|
||||
|
||||
if(item != null && entity.items.get(item) < itemCapacity){
|
||||
useContent(tile, item);
|
||||
offloadNear(tile, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ public class SolidPump extends Pump{
|
||||
tile.entity.liquids.add(result, maxPump);
|
||||
entity.lastPump = maxPump;
|
||||
entity.warmup = Mathf.lerpDelta(entity.warmup, 1f, 0.02f);
|
||||
if(tile.entity.timer.get(timerContentCheck, 10)) useContent(tile, result);
|
||||
if(Mathf.chance(entity.delta() * updateEffectChance))
|
||||
Effects.effect(updateEffect, entity.x + Mathf.range(size * 2f), entity.y + Mathf.range(size * 2f));
|
||||
}else{
|
||||
|
||||
@@ -81,7 +81,7 @@ public class ItemSource extends Block{
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
ItemSourceEntity entity = tile.ent();
|
||||
ItemSelection.buildItemTable(table, () -> entity.outputItem, item -> {
|
||||
ItemSelection.buildTable(table, content.items(), () -> entity.outputItem, item -> {
|
||||
lastItem = item;
|
||||
tile.configure(item == null ? -1 : item.id);
|
||||
});
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
package mindustry.world.blocks.sandbox;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.Vars.content;
|
||||
|
||||
public class LiquidSource extends Block{
|
||||
public static Liquid lastLiquid;
|
||||
@@ -82,29 +77,10 @@ public class LiquidSource extends Block{
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
LiquidSourceEntity entity = tile.ent();
|
||||
|
||||
Array<Liquid> items = content.liquids();
|
||||
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
group.setMinCheckCount(0);
|
||||
Table cont = new Table();
|
||||
|
||||
for(int i = 0; i < items.size; i++){
|
||||
final int f = i;
|
||||
ImageButton button = cont.addImageButton(Tex.clear, Styles.clearToggleTransi, 24, () -> control.input.frag.config.hideConfig()).size(38).group(group).get();
|
||||
button.changed(() -> {
|
||||
tile.configure(button.isChecked() ? items.get(f).id : -1);
|
||||
control.input.frag.config.hideConfig();
|
||||
lastLiquid = items.get(f);
|
||||
});
|
||||
button.getStyle().imageUp = new TextureRegionDrawable(items.get(i).icon(Cicon.medium));
|
||||
button.setChecked(entity.source == items.get(i));
|
||||
|
||||
if(i % 4 == 3){
|
||||
cont.row();
|
||||
}
|
||||
}
|
||||
|
||||
table.add(cont);
|
||||
ItemSelection.buildTable(table, content.liquids(), () -> entity.source, liquid -> {
|
||||
lastLiquid = liquid;
|
||||
tile.configure(liquid == null ? -1 : liquid.id);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -123,7 +123,7 @@ public class Unloader extends Block{
|
||||
@Override
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
UnloaderEntity entity = tile.ent();
|
||||
ItemSelection.buildItemTable(table, () -> entity.sortItem, item -> {
|
||||
ItemSelection.buildTable(table, content.items(), () -> entity.sortItem, item -> {
|
||||
lastItem = item;
|
||||
tile.configure(item == null ? -1 : item.id);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package mindustry.world.modules;
|
||||
|
||||
import mindustry.type.Item;
|
||||
import mindustry.type.ItemStack;
|
||||
import mindustry.type.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.content;
|
||||
|
||||
@@ -69,7 +68,7 @@ public class ItemModule extends BlockModule{
|
||||
return total;
|
||||
}
|
||||
|
||||
public Item first(){ // fixme: entangle with take()
|
||||
public Item first(){
|
||||
for(int i = 0; i < items.length; i++){
|
||||
if(items[i] > 0){
|
||||
return content.item(i);
|
||||
@@ -81,12 +80,12 @@ public class ItemModule extends BlockModule{
|
||||
public Item take(){
|
||||
for(int i = 0; i < items.length; i++){
|
||||
int index = (i + takeRotation);
|
||||
if(index >= items.length) index -= items.length; //conditional instead of mod
|
||||
if(index >= items.length) index -= items.length;
|
||||
if(items[index] > 0){
|
||||
items[index] --;
|
||||
total --;
|
||||
takeRotation = index + 1;
|
||||
return content.item(index % items.length);
|
||||
return content.item(index);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user