Merge branch 'master' of https://github.com/Anuken/Mindustry into 6.0
# Conflicts: # core/src/mindustry/graphics/Bloom.java # gradle.properties
This commit is contained in:
@@ -49,7 +49,7 @@ public class Blocks implements ContentList{
|
||||
melter, separator, sporePress, pulverizer, incinerator, coalCentrifuge,
|
||||
|
||||
//sandbox
|
||||
powerSource, powerVoid, itemSource, itemVoid, liquidSource, message, illuminator,
|
||||
powerSource, powerVoid, itemSource, itemVoid, liquidSource, liquidVoid, message, illuminator,
|
||||
|
||||
//defense
|
||||
copperWall, copperWallLarge, titaniumWall, titaniumWallLarge, plastaniumWall, plastaniumWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge,
|
||||
@@ -1827,6 +1827,11 @@ public class Blocks implements ContentList{
|
||||
alwaysUnlocked = true;
|
||||
}};
|
||||
|
||||
liquidVoid = new LiquidVoid("liquid-void"){{
|
||||
requirements(Category.liquid, BuildVisibility.sandboxOnly, ItemStack.with());
|
||||
alwaysUnlocked = true;
|
||||
}};
|
||||
|
||||
message = new MessageBlock("message"){{
|
||||
requirements(Category.effect, ItemStack.with(Items.graphite, 5));
|
||||
}};
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package mindustry.content;
|
||||
|
||||
import arc.struct.Array;
|
||||
import mindustry.ctype.ContentList;
|
||||
import mindustry.type.ItemStack;
|
||||
import mindustry.world.Block;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.content.Blocks.*;
|
||||
|
||||
@@ -318,7 +319,7 @@ public class TechTree implements ContentList{
|
||||
private static TechNode node(Block block, Runnable children){
|
||||
ItemStack[] requirements = new ItemStack[block.requirements.length];
|
||||
for(int i = 0; i < requirements.length; i++){
|
||||
requirements[i] = new ItemStack(block.requirements[i].item, 30 + block.requirements[i].amount * 6);
|
||||
requirements[i] = new ItemStack(block.requirements[i].item, 40 + Mathf.round(Mathf.pow(block.requirements[i].amount, 1.25f) * 6, 10));
|
||||
}
|
||||
|
||||
return new TechNode(block, requirements, children);
|
||||
|
||||
@@ -47,8 +47,8 @@ public class Logic implements ApplicationListener{
|
||||
//blocks that get broken are appended to the team's broken block queue
|
||||
Tile tile = event.tile;
|
||||
Block block = tile.block();
|
||||
//skip null entities or nukes, for obvious reasons; also skip client since they can't modify these requests
|
||||
if(tile.entity == null || tile.block() instanceof NuclearReactor || net.client()) return;
|
||||
//skip null entities or un-rebuildables, for obvious reasons; also skip client since they can't modify these requests
|
||||
if(tile.entity == null || !tile.block().rebuildable || net.client()) return;
|
||||
|
||||
if(block instanceof BuildBlock){
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ public class NetClient implements ApplicationListener{
|
||||
throw new ValidateException(player, "Player has sent a message above the text limit.");
|
||||
}
|
||||
|
||||
String original = message;
|
||||
Events.fire(new PlayerChatEvent(player, message));
|
||||
|
||||
//check if it's a command
|
||||
CommandResponse response = netServer.clientCommands.handleMessage(message, player);
|
||||
@@ -197,8 +197,6 @@ public class NetClient implements ApplicationListener{
|
||||
player.sendMessage(text);
|
||||
}
|
||||
}
|
||||
|
||||
Events.fire(new PlayerChatEvent(player, message, original));
|
||||
}
|
||||
|
||||
public static String colorizeName(int id, String name){
|
||||
@@ -515,7 +513,7 @@ public class NetClient implements ApplicationListener{
|
||||
return Core.settings.getString("usid-" + ip, null);
|
||||
}else{
|
||||
byte[] bytes = new byte[8];
|
||||
new RandomXS128().nextBytes(bytes);
|
||||
new Rand().nextBytes(bytes);
|
||||
String result = new String(Base64Coder.encode(bytes));
|
||||
Core.settings.put("usid-" + ip, result);
|
||||
Core.settings.save();
|
||||
|
||||
@@ -15,6 +15,7 @@ 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.*;
|
||||
@@ -35,7 +36,7 @@ import static mindustry.Vars.*;
|
||||
|
||||
public class NetServer implements ApplicationListener{
|
||||
private final static int maxSnapshotSize = 430, timerBlockSync = 0;
|
||||
private final static float serverSyncTime = 12, kickDuration = 30 * 1000, blockSyncTime = 60 * 8;
|
||||
private final static float serverSyncTime = 12, blockSyncTime = 60 * 8;
|
||||
private final static Vec2 vector = new Vec2();
|
||||
private final static Rect viewport = new Rect();
|
||||
/** If a player goes away of their server-side coordinates by this distance, they get teleported back. */
|
||||
@@ -75,7 +76,7 @@ public class NetServer implements ApplicationListener{
|
||||
public NetServer(){
|
||||
|
||||
net.handleServer(Connect.class, (con, connect) -> {
|
||||
if(admins.isIPBanned(connect.addressTCP)){
|
||||
if(admins.isIPBanned(connect.addressTCP) || admins.isSubnetBanned(connect.addressTCP)){
|
||||
con.kick(KickReason.banned);
|
||||
}
|
||||
});
|
||||
@@ -93,7 +94,7 @@ public class NetServer implements ApplicationListener{
|
||||
|
||||
String uuid = packet.uuid;
|
||||
|
||||
if(admins.isIPBanned(con.address)) return;
|
||||
if(admins.isIPBanned(con.address) || admins.isSubnetBanned(con.address)) return;
|
||||
|
||||
if(con.hasBegunConnecting){
|
||||
con.kick(KickReason.idInUse);
|
||||
@@ -115,7 +116,7 @@ public class NetServer implements ApplicationListener{
|
||||
return;
|
||||
}
|
||||
|
||||
if(Time.millis() - info.lastKicked < kickDuration){
|
||||
if(Time.millis() < info.lastKicked){
|
||||
con.kick(KickReason.recentKick);
|
||||
return;
|
||||
}
|
||||
@@ -413,6 +414,12 @@ public class NetServer implements ApplicationListener{
|
||||
if(player.isLocal){
|
||||
player.sendMessage("[scarlet]Re-synchronizing as the host is pointless.");
|
||||
}else{
|
||||
if(Time.timeSinceMillis(player.getInfo().lastSyncTime) < 1000 * 5){
|
||||
player.sendMessage("[scarlet]You may only /sync every 5 seconds.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.getInfo().lastSyncTime = Time.millis();
|
||||
Call.onWorldDataBegin(player.con);
|
||||
netServer.sendWorldData(player);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ public interface Platform{
|
||||
String uuid = Core.settings.getString("uuid", "");
|
||||
if(uuid.isEmpty()){
|
||||
byte[] result = new byte[8];
|
||||
new RandomXS128().nextBytes(result);
|
||||
new Rand().nextBytes(result);
|
||||
uuid = new String(Base64Coder.encode(result));
|
||||
Core.settings.put("uuid", uuid);
|
||||
Core.settings.save();
|
||||
|
||||
@@ -118,7 +118,7 @@ public enum EditorTool{
|
||||
if(editor.drawBlock.isOverlay()){
|
||||
Block dest = tile.overlay();
|
||||
if(dest == editor.drawBlock) return;
|
||||
tester = t -> t.overlay() == dest;
|
||||
tester = t -> t.overlay() == dest && !t.floor().isLiquid;
|
||||
setter = t -> t.setOverlay(editor.drawBlock);
|
||||
}else if(editor.drawBlock.isFloor()){
|
||||
Block dest = tile.floor();
|
||||
|
||||
@@ -55,7 +55,7 @@ public class Predict{
|
||||
* See {@link #intercept(float, float, float, float, float, float, float)}.
|
||||
*/
|
||||
public static Vec2 intercept(TargetTrait src, TargetTrait dst, float v){
|
||||
return intercept(src.getX(), src.getY(), dst.getX(), dst.getY(), dst.getTargetVelocityX() - src.getTargetVelocityX()/2f, dst.getTargetVelocityY() - src.getTargetVelocityY()/2f, v);
|
||||
return intercept(src.getX(), src.getY(), dst.getX(), dst.getY(), dst.getTargetVelocityX() - src.getTargetVelocityX()/(2f*Time.delta()), dst.getTargetVelocityY() - src.getTargetVelocityY()/(2f*Time.delta()), v);
|
||||
}
|
||||
|
||||
private static Vec2 quad(float a, float b, float c){
|
||||
|
||||
@@ -27,7 +27,7 @@ import static mindustry.Vars.*;
|
||||
public class Lightning extends TimedEntity implements DrawTrait, TimeTrait{
|
||||
public static final float lifetime = 10f;
|
||||
|
||||
private static final RandomXS128 random = new RandomXS128();
|
||||
private static final Rand random = new Rand();
|
||||
private static final Rect rect = new Rect();
|
||||
private static final Array<Unit> entities = new Array<>();
|
||||
private static final IntSet hit = new IntSet();
|
||||
|
||||
@@ -48,8 +48,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
public float baseRotation;
|
||||
public float pointerX, pointerY;
|
||||
public String name = "noname";
|
||||
public @Nullable
|
||||
String uuid, usid;
|
||||
public @Nullable String uuid, usid;
|
||||
public boolean isAdmin, isTransferring, isShooting, isBoosting, isMobile, isTyping, isBuilding = true;
|
||||
public boolean buildWasAutoPaused = false;
|
||||
public float boostHeat, shootHeat, destructTime;
|
||||
@@ -350,13 +349,13 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
public void drawBackItems(){
|
||||
drawBackItems(itemtime, isLocal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawStats(){
|
||||
Draw.color(Color.black, team.color, healthf() + Mathf.absin(Time.time(), healthf() * 5f, 1f - healthf()));
|
||||
Draw.rect(getPowerCellRegion(), x + Angles.trnsx(rotation, mech.cellTrnsY, 0f), y + Angles.trnsy(rotation, mech.cellTrnsY, 0f), rotation - 90);
|
||||
Draw.reset();
|
||||
drawBackItems(itemtime, isLocal);
|
||||
drawLight();
|
||||
mech.drawStats(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -252,6 +252,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
Tile tile = world.tileWorld(x, y);
|
||||
|
||||
status.update(this);
|
||||
item.amount = Mathf.clamp(this.item.amount, 0, getItemCapacity());
|
||||
|
||||
velocity.limit(maxVelocity()).scl(1f + (status.getSpeedMultiplier() - 1f) * Time.delta());
|
||||
|
||||
@@ -341,6 +342,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
public void addItem(Item item, int amount){
|
||||
this.item.amount = this.item.item == item ? this.item.amount + amount : amount;
|
||||
this.item.item = item;
|
||||
this.item.amount = Mathf.clamp(this.item.amount, 0, getItemCapacity());
|
||||
}
|
||||
|
||||
public void clearItem(){
|
||||
|
||||
@@ -64,13 +64,10 @@ public class EventType{
|
||||
public static class PlayerChatEvent{
|
||||
public final Player player;
|
||||
public final String message;
|
||||
/** The original, unfiltered message. */
|
||||
public final String originalMessage;
|
||||
|
||||
public PlayerChatEvent(Player player, String message, String originalMessage){
|
||||
public PlayerChatEvent(Player player, String message){
|
||||
this.player = player;
|
||||
this.message = message;
|
||||
this.originalMessage = originalMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class Team implements Comparable<Team>{
|
||||
for(int i = 6; i < all.length; i++){
|
||||
new Team(i, "team#" + i, Color.HSVtoRGB(360f * Mathf.random(), 100f * Mathf.random(0.6f, 1f), 100f * Mathf.random(0.8f, 1f), 1f));
|
||||
}
|
||||
Mathf.random.setSeed(new RandomXS128().nextLong());
|
||||
Mathf.random.setSeed(new Rand().nextLong());
|
||||
}
|
||||
|
||||
public static Team get(int id){
|
||||
|
||||
@@ -14,7 +14,6 @@ import arc.graphics.gl.Shader;
|
||||
* @author kalle_h
|
||||
*/
|
||||
public class Bloom{
|
||||
|
||||
/**
|
||||
* To use implement bloom more like a glow. Texture alpha channel can be
|
||||
* used as mask which part are glowing and which are not. see more info at:
|
||||
@@ -61,10 +60,8 @@ public class Bloom{
|
||||
*/
|
||||
public void resume(){
|
||||
bloomShader.begin();
|
||||
{
|
||||
bloomShader.setUniformi("u_texture0", 0);
|
||||
bloomShader.setUniformi("u_texture1", 1);
|
||||
}
|
||||
bloomShader.setUniformi("u_texture0", 0);
|
||||
bloomShader.setUniformi("u_texture1", 1);
|
||||
bloomShader.end();
|
||||
|
||||
setSize(w, h);
|
||||
@@ -83,13 +80,11 @@ public class Bloom{
|
||||
* blending = false 32bits = true
|
||||
*/
|
||||
public Bloom(){
|
||||
initialize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4,
|
||||
null, false, false, true);
|
||||
initialize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4, null, false, false, true);
|
||||
}
|
||||
|
||||
public Bloom(boolean useBlending){
|
||||
initialize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4,
|
||||
null, false, useBlending, true);
|
||||
initialize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4, null, false, useBlending, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,8 +100,7 @@ public class Bloom{
|
||||
* and only do blooming on certain objects param use32bitFBO does
|
||||
* fbo use higher precision than 16bits.
|
||||
*/
|
||||
public Bloom(int FBO_W, int FBO_H, boolean hasDepth, boolean useBlending,
|
||||
boolean use32bitFBO){
|
||||
public Bloom(int FBO_W, int FBO_H, boolean hasDepth, boolean useBlending, boolean use32bitFBO){
|
||||
initialize(FBO_W, FBO_H, null, hasDepth, useBlending, use32bitFBO);
|
||||
|
||||
}
|
||||
@@ -129,18 +123,14 @@ public class Bloom{
|
||||
* and only do blooming on certain objects param use32bitFBO does
|
||||
* fbo use higher precision than 16bits.
|
||||
*/
|
||||
public Bloom(int FBO_W, int FBO_H, FrameBuffer sceneIsCapturedHere,
|
||||
boolean useBlending, boolean use32bitFBO){
|
||||
|
||||
initialize(FBO_W, FBO_H, sceneIsCapturedHere, false, useBlending,
|
||||
use32bitFBO);
|
||||
public Bloom(int FBO_W, int FBO_H, FrameBuffer sceneIsCapturedHere, boolean useBlending, boolean use32bitFBO){
|
||||
initialize(FBO_W, FBO_H, sceneIsCapturedHere, false, useBlending, use32bitFBO);
|
||||
disposeFBO = false;
|
||||
}
|
||||
|
||||
private void initialize(int FBO_W, int FBO_H, FrameBuffer fbo,
|
||||
boolean hasDepth, boolean useBlending, boolean use32bitFBO){
|
||||
private void initialize(int FBO_W, int FBO_H, FrameBuffer fbo, boolean hasDepth, boolean useBlending, boolean use32bitFBO){
|
||||
blending = useBlending;
|
||||
Format format = null;
|
||||
Format format;
|
||||
|
||||
if(use32bitFBO){
|
||||
if(useBlending){
|
||||
@@ -157,8 +147,7 @@ public class Bloom{
|
||||
}
|
||||
}
|
||||
if(fbo == null){
|
||||
frameBuffer = new FrameBuffer(format, Core.graphics.getWidth(),
|
||||
Core.graphics.getHeight(), hasDepth);
|
||||
frameBuffer = new FrameBuffer(format, Core.graphics.getWidth(), Core.graphics.getHeight(), hasDepth);
|
||||
}else{
|
||||
frameBuffer = fbo;
|
||||
}
|
||||
@@ -190,10 +179,8 @@ public class Bloom{
|
||||
setThreshold(0.5f);
|
||||
|
||||
bloomShader.begin();
|
||||
{
|
||||
bloomShader.setUniformi("u_texture0", 0);
|
||||
bloomShader.setUniformi("u_texture1", 1);
|
||||
}
|
||||
bloomShader.setUniformi("u_texture0", 0);
|
||||
bloomShader.setUniformi("u_texture1", 1);
|
||||
bloomShader.end();
|
||||
}
|
||||
|
||||
@@ -219,8 +206,8 @@ public class Bloom{
|
||||
if(!capturing){
|
||||
capturing = true;
|
||||
frameBuffer.begin();
|
||||
Core.gl.glClearColor(r, g, b, a);
|
||||
Core.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||
Gl.clearColor(r, g, b, a);
|
||||
Gl.clear(Gl.colorBufferBit);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -252,23 +239,22 @@ public class Bloom{
|
||||
frameBuffer.end();
|
||||
}
|
||||
|
||||
Core.gl.glDisable(GL20.GL_BLEND);
|
||||
Core.gl.glDisable(GL20.GL_DEPTH_TEST);
|
||||
Core.gl.glDepthMask(false);
|
||||
Gl.disable(Gl.blend);
|
||||
Gl.disable(Gl.depthTest);
|
||||
Gl.depthMask(false);
|
||||
|
||||
gaussianBlur();
|
||||
|
||||
if(blending){
|
||||
Core.gl.glEnable(GL20.GL_BLEND);
|
||||
Core.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
|
||||
Gl.enable(Gl.blend);
|
||||
Gl.blendFunc(Gl.srcAlpha, Gl.oneMinusSrcAlpha);
|
||||
}
|
||||
|
||||
pingPongTex1.bind(1);
|
||||
original.bind(0);
|
||||
|
||||
bloomShader.begin();
|
||||
{
|
||||
fullScreenQuad.render(bloomShader, GL20.GL_TRIANGLE_FAN);
|
||||
}
|
||||
fullScreenQuad.render(bloomShader, Gl.triangleFan);
|
||||
bloomShader.end();
|
||||
|
||||
}
|
||||
@@ -279,15 +265,9 @@ public class Bloom{
|
||||
|
||||
original.bind(0);
|
||||
pingPongBuffer1.begin();
|
||||
{
|
||||
tresholdShader.begin();
|
||||
{
|
||||
// tresholdShader.setUniformi("u_texture0", 0);
|
||||
fullScreenQuad.render(tresholdShader, GL20.GL_TRIANGLE_FAN, 0,
|
||||
4);
|
||||
}
|
||||
tresholdShader.end();
|
||||
}
|
||||
tresholdShader.begin();
|
||||
fullScreenQuad.render(tresholdShader, Gl.triangleFan, 0, 4);
|
||||
tresholdShader.end();
|
||||
pingPongBuffer1.end();
|
||||
|
||||
for(int i = 0; i < blurPasses; i++){
|
||||
@@ -296,30 +276,19 @@ public class Bloom{
|
||||
|
||||
// horizontal
|
||||
pingPongBuffer2.begin();
|
||||
{
|
||||
blurShader.begin();
|
||||
{
|
||||
blurShader.setUniformf("dir", 1f, 0f);
|
||||
fullScreenQuad.render(blurShader, GL20.GL_TRIANGLE_FAN, 0,
|
||||
4);
|
||||
}
|
||||
blurShader.end();
|
||||
}
|
||||
blurShader.begin();
|
||||
blurShader.setUniformf("dir", 1f, 0f);
|
||||
fullScreenQuad.render(blurShader, Gl.triangleFan, 0, 4);
|
||||
blurShader.end();
|
||||
pingPongBuffer2.end();
|
||||
|
||||
pingPongTex2.bind(0);
|
||||
// vertical
|
||||
pingPongBuffer1.begin();
|
||||
{
|
||||
blurShader.begin();
|
||||
{
|
||||
blurShader.setUniformf("dir", 0f, 1f);
|
||||
|
||||
fullScreenQuad.render(blurShader, GL20.GL_TRIANGLE_FAN, 0,
|
||||
4);
|
||||
}
|
||||
blurShader.end();
|
||||
}
|
||||
blurShader.begin();
|
||||
blurShader.setUniformf("dir", 0f, 1f);
|
||||
fullScreenQuad.render(blurShader, Gl.triangleFan, 0, 4);
|
||||
blurShader.end();
|
||||
pingPongBuffer1.end();
|
||||
}
|
||||
}
|
||||
@@ -334,9 +303,7 @@ public class Bloom{
|
||||
public void setBloomIntesity(float intensity){
|
||||
bloomIntensity = intensity;
|
||||
bloomShader.begin();
|
||||
{
|
||||
bloomShader.setUniformf("BloomIntensity", intensity);
|
||||
}
|
||||
bloomShader.setUniformf("BloomIntensity", intensity);
|
||||
bloomShader.end();
|
||||
}
|
||||
|
||||
@@ -350,9 +317,7 @@ public class Bloom{
|
||||
public void setOriginalIntesity(float intensity){
|
||||
originalIntensity = intensity;
|
||||
bloomShader.begin();
|
||||
{
|
||||
bloomShader.setUniformf("OriginalIntensity", intensity);
|
||||
}
|
||||
bloomShader.setUniformf("OriginalIntensity", intensity);
|
||||
bloomShader.end();
|
||||
}
|
||||
|
||||
@@ -364,10 +329,7 @@ public class Bloom{
|
||||
public void setThreshold(float threshold){
|
||||
this.threshold = threshold;
|
||||
tresholdShader.begin();
|
||||
{
|
||||
tresholdShader.setUniformf("threshold", threshold,
|
||||
1f / (1 - threshold));
|
||||
}
|
||||
tresholdShader.setUniformf("threshold", threshold, 1f / (1 - threshold));
|
||||
tresholdShader.end();
|
||||
}
|
||||
|
||||
@@ -384,8 +346,7 @@ public class Bloom{
|
||||
*/
|
||||
public void dispose(){
|
||||
try{
|
||||
if(disposeFBO)
|
||||
frameBuffer.dispose();
|
||||
if(disposeFBO) frameBuffer.dispose();
|
||||
|
||||
fullScreenQuad.dispose();
|
||||
|
||||
@@ -395,16 +356,17 @@ public class Bloom{
|
||||
blurShader.dispose();
|
||||
bloomShader.dispose();
|
||||
tresholdShader.dispose();
|
||||
}catch(Exception ignored){
|
||||
}catch(Throwable ignored){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static Mesh createFullScreenQuad(){
|
||||
float[] verts = {-1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1};
|
||||
Mesh tmpMesh = new Mesh(true, 4, 0, new VertexAttribute(
|
||||
Usage.position, 2, "a_position"), new VertexAttribute(
|
||||
Usage.textureCoordinates, 2, "a_texCoord0"));
|
||||
Mesh tmpMesh = new Mesh(true, 4, 0,
|
||||
new VertexAttribute(Usage.position, 2, "a_position"),
|
||||
new VertexAttribute(Usage.textureCoordinates, 2, "a_texCoord0")
|
||||
);
|
||||
|
||||
tmpMesh.setVertices(verts);
|
||||
return tmpMesh;
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
package mindustry.graphics;
|
||||
|
||||
import arc.Core;
|
||||
import arc.Events;
|
||||
import arc.struct.*;
|
||||
import arc.struct.IntSet.IntSetIterator;
|
||||
import arc.graphics.Camera;
|
||||
import arc.graphics.GL20;
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.struct.IntSet.*;
|
||||
import arc.util.*;
|
||||
import mindustry.game.EventType.WorldLoadEvent;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.blocks.Floor;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.tilesize;
|
||||
import static mindustry.Vars.world;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class FloorRenderer implements Disposable{
|
||||
private final static int chunksize = 64;
|
||||
@@ -104,7 +101,7 @@ public class FloorRenderer implements Disposable{
|
||||
cbatch.setProjection(Core.camera.projection());
|
||||
cbatch.beginDraw();
|
||||
|
||||
Core.gl.glEnable(GL20.GL_BLEND);
|
||||
Gl.enable(Gl.blend);
|
||||
}
|
||||
|
||||
public void endDraw(){
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
package mindustry.graphics;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.VertexAttributes.Usage;
|
||||
import arc.graphics.g2d.BatchShader;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import arc.graphics.gl.Shader;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.Matrix3;
|
||||
import arc.util.Disposable;
|
||||
import arc.util.Strings;
|
||||
import arc.graphics.VertexAttributes.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.gl.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
|
||||
//TODO this class is a trainwreck, remove it
|
||||
public class IndexedRenderer implements Disposable{
|
||||
@@ -50,9 +46,9 @@ public class IndexedRenderer implements Disposable{
|
||||
private float[] tmpVerts = new float[vsize * 6];
|
||||
private float[] vertices;
|
||||
|
||||
private Matrix3 projMatrix = new Matrix3();
|
||||
private Matrix3 transMatrix = new Matrix3();
|
||||
private Matrix3 combined = new Matrix3();
|
||||
private Mat projMatrix = new Mat();
|
||||
private Mat transMatrix = new Mat();
|
||||
private Mat combined = new Mat();
|
||||
private float color = Color.white.toFloatBits();
|
||||
|
||||
public IndexedRenderer(int sprites){
|
||||
@@ -60,7 +56,7 @@ public class IndexedRenderer implements Disposable{
|
||||
}
|
||||
|
||||
public void render(Texture texture){
|
||||
Core.gl.glEnable(GL20.GL_BLEND);
|
||||
Gl.enable(Gl.blend);
|
||||
|
||||
updateMatrix();
|
||||
|
||||
@@ -71,7 +67,7 @@ public class IndexedRenderer implements Disposable{
|
||||
program.setUniformMatrix4("u_projTrans", BatchShader.copyTransform(combined));
|
||||
program.setUniformi("u_texture", 0);
|
||||
|
||||
mesh.render(program, GL20.GL_TRIANGLES, 0, vertices.length / vsize);
|
||||
mesh.render(program, Gl.triangles, 0, vertices.length / vsize);
|
||||
|
||||
program.end();
|
||||
}
|
||||
@@ -214,11 +210,11 @@ public class IndexedRenderer implements Disposable{
|
||||
mesh.updateVertices(index * vsize * 6, vertices);
|
||||
}
|
||||
|
||||
public Matrix3 getTransformMatrix(){
|
||||
public Mat getTransformMatrix(){
|
||||
return transMatrix;
|
||||
}
|
||||
|
||||
public void setProjectionMatrix(Matrix3 matrix){
|
||||
public void setProjectionMatrix(Mat matrix){
|
||||
projMatrix = matrix;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class MenuRenderer implements Disposable{
|
||||
|
||||
private int cacheFloor, cacheWall;
|
||||
private Camera camera = new Camera();
|
||||
private Matrix3 mat = new Matrix3();
|
||||
private Mat mat = new Mat();
|
||||
private FrameBuffer shadows;
|
||||
private CacheBatch batch;
|
||||
private float time = 0f;
|
||||
|
||||
@@ -64,7 +64,7 @@ public class OverlayRenderer{
|
||||
for(Tile mechpad : indexer.getAllied(player.getTeam(), BlockFlag.mechPad)){
|
||||
if(!(mechpad.block() instanceof MechPad)) continue;
|
||||
if(!rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f)
|
||||
.setCenter(Core.camera.position.x, Core.camera.position.y).contains(mechpad.x, mechpad.y)){
|
||||
.setCenter(Core.camera.position.x, Core.camera.position.y).contains(mechpad.drawx(), mechpad.drawy())){
|
||||
|
||||
Tmp.v1.set(mechpad.drawx(), mechpad.drawy()).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength);
|
||||
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
package mindustry.net;
|
||||
|
||||
import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import arc.util.pooling.*;
|
||||
import arc.util.pooling.Pool.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.headless;
|
||||
import static mindustry.game.EventType.*;
|
||||
@@ -16,9 +22,61 @@ public class Administration{
|
||||
private Array<String> bannedIPs = new Array<>();
|
||||
private Array<String> whitelist = new Array<>();
|
||||
private Array<ChatFilter> chatFilters = new Array<>();
|
||||
private Array<ActionFilter> actionFilters = new Array<>();
|
||||
private Array<String> subnetBans = new Array<>();
|
||||
|
||||
public Administration(){
|
||||
load();
|
||||
|
||||
//anti-spam
|
||||
addChatFilter((player, message) -> {
|
||||
long resetTime = Config.messageRateLimit.num() * 1000;
|
||||
if(Config.antiSpam.bool() && !player.isLocal && !player.isAdmin){
|
||||
//prevent people from spamming messages quickly
|
||||
if(resetTime > 0 && Time.timeSinceMillis(player.getInfo().lastMessageTime) < resetTime){
|
||||
//supress message
|
||||
player.sendMessage("[scarlet]You may only send messages every " + Config.messageRateLimit.num() + " seconds.");
|
||||
player.getInfo().messageInfractions ++;
|
||||
//kick player for spamming and prevent connection if they've done this several times
|
||||
if(player.getInfo().messageInfractions >= Config.messageSpamKick.num() && Config.messageSpamKick.num() != 0){
|
||||
player.con.kick("You have been kicked for spamming.", 1000 * 60 * 2);
|
||||
}
|
||||
player.getInfo().lastSentMessage = message;
|
||||
return null;
|
||||
}else{
|
||||
player.getInfo().messageInfractions = 0;
|
||||
}
|
||||
|
||||
//prevent players from sending the same message twice in the span of 50 seconds
|
||||
if(message.equals(player.getInfo().lastSentMessage) && Time.timeSinceMillis(player.getInfo().lastMessageTime) < 1000 * 50){
|
||||
player.sendMessage("[scarlet]You may not send the same message twice.");
|
||||
return null;
|
||||
}
|
||||
|
||||
player.getInfo().lastSentMessage = message;
|
||||
player.getInfo().lastMessageTime = Time.millis();
|
||||
}
|
||||
|
||||
return message;
|
||||
});
|
||||
}
|
||||
|
||||
public Array<String> getSubnetBans(){
|
||||
return subnetBans;
|
||||
}
|
||||
|
||||
public void removeSubnetBan(String ip){
|
||||
subnetBans.remove(ip);
|
||||
save();
|
||||
}
|
||||
|
||||
public void addSubnetBan(String ip){
|
||||
subnetBans.add(ip);
|
||||
save();
|
||||
}
|
||||
|
||||
public boolean isSubnetBanned(String ip){
|
||||
return subnetBans.contains(ip::startsWith);
|
||||
}
|
||||
|
||||
/** Adds a chat filter. This will transform the chat messages of every player.
|
||||
@@ -38,6 +96,25 @@ public class Administration{
|
||||
return current;
|
||||
}
|
||||
|
||||
/** Add a filter to actions, preventing things such as breaking or configuring blocks. */
|
||||
public void addActionFilter(ActionFilter filter){
|
||||
actionFilters.add(filter);
|
||||
}
|
||||
|
||||
/** @return whether this action is allowed by the action filters. */
|
||||
public boolean allowAction(Player player, ActionType type, Tile tile, Cons<PlayerAction> setter){
|
||||
PlayerAction act = Pools.obtain(PlayerAction.class, PlayerAction::new);
|
||||
setter.get(act.set(player, type, tile));
|
||||
for(ActionFilter filter : actionFilters){
|
||||
if(!filter.allow(act)){
|
||||
Pools.free(act);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Pools.free(act);
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getPlayerLimit(){
|
||||
return Core.settings.getInt("playerlimit", 0);
|
||||
}
|
||||
@@ -305,6 +382,7 @@ public class Administration{
|
||||
Core.settings.putObject("player-info", playerInfo);
|
||||
Core.settings.putObject("banned-ips", bannedIPs);
|
||||
Core.settings.putObject("whitelisted", whitelist);
|
||||
Core.settings.putObject("subnet-bans", subnetBans);
|
||||
Core.settings.save();
|
||||
}
|
||||
|
||||
@@ -313,6 +391,7 @@ public class Administration{
|
||||
playerInfo = Core.settings.getObject("player-info", ObjectMap.class, ObjectMap::new);
|
||||
bannedIPs = Core.settings.getObject("banned-ips", Array.class, Array::new);
|
||||
whitelist = Core.settings.getObject("whitelisted", Array.class, Array::new);
|
||||
subnetBans = Core.settings.getObject("subnet-bans", Array.class, Array::new);
|
||||
}
|
||||
|
||||
/** Server configuration definition. Each config value can be a string, boolean or number. */
|
||||
@@ -326,6 +405,9 @@ public class Administration{
|
||||
crashReport("Whether to send crash reports.", false, "crashreport"),
|
||||
logging("Whether to log everything to files.", true),
|
||||
strict("Whether strict mode is on - corrects positions and prevents duplicate UUIDs.", true),
|
||||
antiSpam("Whether spammers are automatically kicked and rate-limited.", true),
|
||||
messageRateLimit("Message rate limit in seconds. 0 to disable.", 0),
|
||||
messageSpamKick("How many times a player must send a message before the cooldown to get kicked. 0 to disable.", 3),
|
||||
socketInput("Allows a local application to control this server through a local TCP socket.", false, "socket", () -> Events.fire(Trigger.socketConfigChanged)),
|
||||
socketInputPort("The port for socket input.", 6859, () -> Events.fire(Trigger.socketConfigChanged)),
|
||||
socketInputAddress("The bind address for socket input.", "localhost", () -> Events.fire(Trigger.socketConfigChanged)),
|
||||
@@ -402,7 +484,11 @@ public class Administration{
|
||||
public int timesKicked;
|
||||
public int timesJoined;
|
||||
public boolean banned, admin;
|
||||
public long lastKicked; //last kicked timestamp
|
||||
public long lastKicked; //last kicked time to expiration
|
||||
|
||||
public transient long lastMessageTime, lastSyncTime;
|
||||
public transient String lastSentMessage;
|
||||
public transient int messageInfractions;
|
||||
|
||||
PlayerInfo(String id){
|
||||
this.id = id;
|
||||
@@ -412,11 +498,18 @@ public class Administration{
|
||||
}
|
||||
}
|
||||
|
||||
/** Handles chat messages from players and changes their contents. */
|
||||
public interface ChatFilter{
|
||||
/** @return the filtered message; a null string signals that the message should not be sent. */
|
||||
@Nullable String filter(Player player, String message);
|
||||
}
|
||||
|
||||
/** Allows or disallows player actions. */
|
||||
public interface ActionFilter{
|
||||
/** @return whether this action should be permitted. if applicable, make sure to send this player a message specify why the action was prohibited. */
|
||||
boolean allow(PlayerAction action);
|
||||
}
|
||||
|
||||
public static class TraceInfo{
|
||||
public String ip, uuid;
|
||||
public boolean modded, mobile;
|
||||
@@ -429,4 +522,39 @@ public class Administration{
|
||||
}
|
||||
}
|
||||
|
||||
/** Defines a (potentially dangerous) action that a player has done in the world.
|
||||
* These objects are pooled; do not cache them! */
|
||||
public static class PlayerAction implements Poolable{
|
||||
public @NonNull Player player;
|
||||
public @NonNull ActionType type;
|
||||
public @NonNull Tile tile;
|
||||
|
||||
/** valid for configure and rotation-type events only. */
|
||||
public int config;
|
||||
|
||||
/** valid for item-type events only. */
|
||||
public @Nullable Item item;
|
||||
public int itemAmount;
|
||||
|
||||
public PlayerAction set(Player player, ActionType type, Tile tile){
|
||||
this.player = player;
|
||||
this.type = type;
|
||||
this.tile = tile;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
item = null;
|
||||
itemAmount = config = 0;
|
||||
player = null;
|
||||
type = null;
|
||||
tile = null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ActionType{
|
||||
breakBlock, placeBlock, rotate, configure, withdrawItem, depositItem
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@ import static mindustry.Vars.netServer;
|
||||
public abstract class NetConnection{
|
||||
public final String address;
|
||||
public boolean mobile, modclient;
|
||||
public @Nullable
|
||||
Player player;
|
||||
public @Nullable Player player;
|
||||
|
||||
/** ID of last recieved client snapshot. */
|
||||
public int lastRecievedClientSnapshot = -1;
|
||||
@@ -37,7 +36,7 @@ public abstract class NetConnection{
|
||||
if(player != null && (reason == KickReason.kick || reason == KickReason.banned || reason == KickReason.vote) && player.uuid != null){
|
||||
PlayerInfo info = netServer.admins.getInfo(player.uuid);
|
||||
info.timesKicked++;
|
||||
info.lastKicked = Math.max(Time.millis(), info.lastKicked);
|
||||
info.lastKicked = Math.max(Time.millis() + 30 * 1000, info.lastKicked);
|
||||
}
|
||||
|
||||
Call.onKick(this, reason);
|
||||
@@ -49,12 +48,17 @@ public abstract class NetConnection{
|
||||
|
||||
/** Kick with an arbitrary reason. */
|
||||
public void kick(String reason){
|
||||
kick(reason, 30 * 1000);
|
||||
}
|
||||
|
||||
/** Kick with an arbitrary reason, and a kick duration in milliseconds. */
|
||||
public void kick(String reason, int kickDuration){
|
||||
Log.info("Kicking connection {0}; Reason: {1}", address, reason.replace("\n", " "));
|
||||
|
||||
if(player != null && player.uuid != null){
|
||||
PlayerInfo info = netServer.admins.getInfo(player.uuid);
|
||||
info.timesKicked++;
|
||||
info.lastKicked = Math.max(Time.millis(), info.lastKicked);
|
||||
info.lastKicked = Math.max(Time.millis() + kickDuration, info.lastKicked);
|
||||
}
|
||||
|
||||
Call.onKick(this, reason);
|
||||
|
||||
@@ -2,9 +2,11 @@ package mindustry.type;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.Color;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.Table;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.Time;
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.entities.type.Player;
|
||||
import mindustry.ctype.UnlockableContent;
|
||||
@@ -32,6 +34,13 @@ public class Mech extends UnlockableContent{
|
||||
public boolean canHeal = false;
|
||||
public float compoundSpeed, compoundSpeedBoost;
|
||||
|
||||
/** draw the health and team indicator */
|
||||
public boolean drawCell = true;
|
||||
/** draw the items on its back */
|
||||
public boolean drawItems = true;
|
||||
/** draw the engine light if it's flying/boosting */
|
||||
public boolean drawLight = true;
|
||||
|
||||
public float weaponOffsetX, weaponOffsetY, engineOffset = 5f, engineSize = 2.5f;
|
||||
public @NonNull Weapon weapon;
|
||||
|
||||
@@ -52,6 +61,24 @@ public class Mech extends UnlockableContent{
|
||||
public void draw(Player player){
|
||||
}
|
||||
|
||||
public void drawStats(Player player){
|
||||
if(drawCell){
|
||||
float health = player.healthf();
|
||||
Draw.color(Color.black, player.getTeam().color, health + Mathf.absin(Time.time(), health * 5f, 1f - health));
|
||||
Draw.rect(player.getPowerCellRegion(),
|
||||
player.x + Angles.trnsx(player.rotation, cellTrnsY, 0f),
|
||||
player.y + Angles.trnsy(player.rotation, cellTrnsY, 0f),
|
||||
player.rotation - 90);
|
||||
Draw.reset();
|
||||
}
|
||||
if(drawItems){
|
||||
player.drawBackItems();
|
||||
}
|
||||
if(drawLight){
|
||||
player.drawLight();
|
||||
}
|
||||
}
|
||||
|
||||
public float getExtraArmor(Player player){
|
||||
return 0f;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ public class AboutDialog extends FloatingDialog{
|
||||
public void showCredits(){
|
||||
FloatingDialog dialog = new FloatingDialog("$credits");
|
||||
dialog.addCloseButton();
|
||||
dialog.cont.add("$credits.text");
|
||||
dialog.cont.add("$credits.text").fillX().wrap().get().setAlignment(Align.center);
|
||||
dialog.cont.row();
|
||||
if(!contributors.isEmpty()){
|
||||
dialog.cont.addImage().color(Pal.accent).fillX().height(3f).pad(3f);
|
||||
|
||||
@@ -268,6 +268,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
}
|
||||
return s + "%";
|
||||
});
|
||||
graphics.sliderPref("bridgeopacity", 75, 0, 100, 5, s -> s + "%");
|
||||
|
||||
if(!mobile){
|
||||
graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b));
|
||||
|
||||
@@ -55,6 +55,8 @@ public class Block extends BlockStorage{
|
||||
public boolean rotate;
|
||||
/** whether you can break this with rightclick */
|
||||
public boolean breakable;
|
||||
/** whether to add this block to brokenblocks */
|
||||
public boolean rebuildable = true;
|
||||
/** whether this floor can be placed on. */
|
||||
public boolean placeableOn = true;
|
||||
/** whether this block has insulating properties. */
|
||||
|
||||
@@ -26,6 +26,7 @@ public class ShockMine extends Block{
|
||||
solid = false;
|
||||
targetable = false;
|
||||
layer = Layer.overlay;
|
||||
rebuildable = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.Geometry;
|
||||
import mindustry.world.Tile;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -31,6 +32,10 @@ public class ExtendingItemBridge extends ItemBridge{
|
||||
ex *= uptime;
|
||||
ey *= uptime;
|
||||
|
||||
float opacity = Core.settings.getInt("bridgeopacity") / 100f;
|
||||
if(Mathf.zero(opacity)) return;
|
||||
Draw.alpha(opacity);
|
||||
|
||||
Lines.stroke(8f);
|
||||
Lines.line(bridgeRegion,
|
||||
tile.worldx() + Geometry.d4[i].x * tilesize / 2f,
|
||||
@@ -50,7 +55,7 @@ public class ExtendingItemBridge extends ItemBridge{
|
||||
Draw.color();
|
||||
|
||||
for(int a = 0; a < arrows; a++){
|
||||
Draw.alpha(Mathf.absin(a / (float)arrows - entity.time / 100f, 0.1f, 1f) * uptime);
|
||||
Draw.alpha(Mathf.absin(a / (float)arrows - entity.time / 100f, 0.1f, 1f) * uptime * opacity);
|
||||
Draw.rect(arrowRegion,
|
||||
tile.worldx() + Geometry.d4[i].x * (tilesize / 2f + a * 6f + 2) * uptime,
|
||||
tile.worldy() + Geometry.d4[i].y * (tilesize / 2f + a * 6f + 2) * uptime, i * 90f);
|
||||
|
||||
@@ -219,10 +219,13 @@ public class ItemBridge extends Block{
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)) return;
|
||||
|
||||
float opacity = Core.settings.getInt("bridgeopacity") / 100f;
|
||||
if(Mathf.zero(opacity)) return;
|
||||
|
||||
int i = tile.absoluteRelativeTo(other.x, other.y);
|
||||
|
||||
Draw.color(Color.white, Color.black, Mathf.absin(Time.time(), 6f, 0.07f));
|
||||
Draw.alpha(Math.max(entity.uptime, 0.25f));
|
||||
Draw.alpha(Math.max(entity.uptime, 0.25f) * opacity);
|
||||
|
||||
Draw.rect(endRegion, tile.drawx(), tile.drawy(), i * 90 + 90);
|
||||
Draw.rect(endRegion, other.drawx(), other.drawy(), i * 90 + 270);
|
||||
@@ -242,7 +245,7 @@ public class ItemBridge extends Block{
|
||||
Draw.color();
|
||||
|
||||
for(int a = 0; a < arrows; a++){
|
||||
Draw.alpha(Mathf.absin(a / (float)arrows - entity.time / 100f, 0.1f, 1f) * entity.uptime);
|
||||
Draw.alpha(Mathf.absin(a / (float)arrows - entity.time / 100f, 0.1f, 1f) * entity.uptime * opacity);
|
||||
Draw.rect(arrowRegion,
|
||||
tile.worldx() + Geometry.d4[i].x * (tilesize / 2f + a * 4f + time % 4f),
|
||||
tile.worldy() + Geometry.d4[i].y * (tilesize / 2f + a * 4f + time % 4f), i * 90f);
|
||||
|
||||
@@ -46,6 +46,7 @@ public class NuclearReactor extends PowerGenerator{
|
||||
hasItems = true;
|
||||
hasLiquids = true;
|
||||
entityType = NuclearReactorEntity::new;
|
||||
rebuildable = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,7 @@ import arc.Core;
|
||||
import arc.graphics.Color;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.RandomXS128;
|
||||
import arc.math.Rand;
|
||||
import arc.util.Time;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
@@ -21,7 +21,7 @@ public class Cultivator extends GenericCrafter{
|
||||
public Color bottomColor = Color.valueOf("474747");
|
||||
|
||||
public TextureRegion middleRegion, topRegion;
|
||||
public RandomXS128 random = new RandomXS128(0);
|
||||
public Rand random = new Rand(0);
|
||||
public float recurrence = 6f;
|
||||
public Attribute attribute = Attribute.spores;
|
||||
|
||||
|
||||
29
core/src/mindustry/world/blocks/sandbox/LiquidVoid.java
Normal file
29
core/src/mindustry/world/blocks/sandbox/LiquidVoid.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package mindustry.world.blocks.sandbox;
|
||||
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class LiquidVoid extends Block{
|
||||
|
||||
public LiquidVoid(String name){
|
||||
super(name);
|
||||
hasLiquids = true;
|
||||
solid = true;
|
||||
update = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBars(){
|
||||
super.setBars();
|
||||
bars.remove("liquid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLiquid(Tile tile, Tile source, Liquid liquid, float amount){}
|
||||
|
||||
}
|
||||
@@ -73,7 +73,7 @@ public class LaunchPad extends StorageBlock{
|
||||
public void update(Tile tile){
|
||||
TileEntity entity = tile.entity;
|
||||
|
||||
if(world.isZone() && entity.cons.valid() && world.isZone() && entity.items.total() >= itemCapacity && entity.timer.get(timerLaunch, launchTime / entity.timeScale)){
|
||||
if(world.isZone() && entity.cons.valid() && entity.items.total() >= itemCapacity && entity.timer.get(timerLaunch, launchTime / entity.timeScale)){
|
||||
for(Item item : Vars.content.items()){
|
||||
Events.fire(Trigger.itemLaunch);
|
||||
Effects.effect(Fx.padlaunch, tile);
|
||||
|
||||
Reference in New Issue
Block a user