Merged with master
This commit is contained in:
@@ -102,7 +102,7 @@ public class Vars{
|
||||
|
||||
public static final int tilesize = 8;
|
||||
|
||||
public static final Locale[] locales = {new Locale("en"), new Locale("fr", "FR"), new Locale("ru"), new Locale("uk", "UA"), new Locale("pl", "PL"),
|
||||
public static final Locale[] locales = {new Locale("en"), new Locale("fr"), new Locale("ru"), new Locale("uk", "UA"), new Locale("pl", "PL"),
|
||||
new Locale("de"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID"), new Locale("ita"), new Locale("es")};
|
||||
|
||||
public static final Color[] playerColors = {
|
||||
|
||||
@@ -103,7 +103,7 @@ public class Control extends Module{
|
||||
|
||||
Sounds.setFalloff(9000f);
|
||||
|
||||
Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3", "5.mp3", "6.mp3");
|
||||
Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3");
|
||||
|
||||
DefaultKeybinds.load();
|
||||
|
||||
@@ -188,6 +188,11 @@ public class Control extends Module{
|
||||
});
|
||||
}
|
||||
|
||||
//FIXME figure out what's causing this problem in the first place
|
||||
public void triggerInputUpdate(){
|
||||
Gdx.input = proxy;
|
||||
}
|
||||
|
||||
public void setError(Throwable error){
|
||||
this.error = error;
|
||||
}
|
||||
@@ -266,9 +271,7 @@ public class Control extends Module{
|
||||
throw new RuntimeException(error);
|
||||
}
|
||||
|
||||
if(Gdx.input != proxy){
|
||||
Gdx.input = proxy;
|
||||
}
|
||||
Gdx.input = proxy;
|
||||
|
||||
if(Inputs.keyTap("console")){
|
||||
console = !console;
|
||||
@@ -292,16 +295,21 @@ public class Control extends Module{
|
||||
controly -= ya*baseControllerSpeed*scl;
|
||||
controlling = true;
|
||||
|
||||
Gdx.input.setCursorCatched(true);
|
||||
|
||||
Inputs.getProcessor().touchDragged(Gdx.input.getX(), Gdx.input.getY(), 0);
|
||||
}
|
||||
|
||||
controlx = Mathf.clamp(controlx, 0, Gdx.graphics.getWidth());
|
||||
controly = Mathf.clamp(controly, 0, Gdx.graphics.getHeight());
|
||||
|
||||
if(Gdx.input.getDeltaX() > 1 || Gdx.input.getDeltaY() > 1)
|
||||
controlling = false;
|
||||
if(Gdx.input.getDeltaX() > 1 || Gdx.input.getDeltaY() > 1) {
|
||||
controlling = false;
|
||||
Gdx.input.setCursorCatched(false);
|
||||
}
|
||||
}else{
|
||||
controlling = false;
|
||||
Gdx.input.setCursorCatched(false);
|
||||
}
|
||||
|
||||
if(!controlling){
|
||||
|
||||
@@ -83,6 +83,8 @@ public class Logic extends Module {
|
||||
|
||||
if(!state.is(State.menu)){
|
||||
|
||||
if(control != null) control.triggerInputUpdate();
|
||||
|
||||
if(!state.is(State.paused) || Net.active()){
|
||||
Timers.update();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import static io.anuke.mindustry.Vars.*;
|
||||
public class NetClient extends Module {
|
||||
private final static float dataTimeout = 60*18;
|
||||
private final static float playerSyncTime = 2;
|
||||
private final static int maxRequests = 50;
|
||||
|
||||
private Timer timer = new Timer(5);
|
||||
/**Whether the client is currently conencting.*/
|
||||
@@ -47,6 +48,7 @@ public class NetClient extends Module {
|
||||
private IntMap<SyncEntity> recent = new IntMap<>();
|
||||
/**Counter for data timeout.*/
|
||||
private float timeoutTime = 0f;
|
||||
private int requests = 0;
|
||||
|
||||
public NetClient(){
|
||||
|
||||
@@ -125,11 +127,12 @@ public class NetClient extends Module {
|
||||
if(entity instanceof BaseUnit) enemies ++;
|
||||
|
||||
if (entity == null || id == player.id) {
|
||||
if (id != player.id) {
|
||||
if (id != player.id && requests < maxRequests) {
|
||||
EntityRequestPacket req = new EntityRequestPacket();
|
||||
req.id = id;
|
||||
req.group = groupid;
|
||||
Net.send(req, SendMode.udp);
|
||||
requests ++;
|
||||
}
|
||||
data.position(data.position() + writesize);
|
||||
} else {
|
||||
@@ -322,6 +325,7 @@ public class NetClient extends Module {
|
||||
}
|
||||
|
||||
void sync(){
|
||||
requests = 0;
|
||||
|
||||
if(timer.get(0, playerSyncTime)){
|
||||
PositionPacket packet = new PositionPacket();
|
||||
|
||||
@@ -179,8 +179,8 @@ public class NetServer extends Module{
|
||||
if(!Timers.get("fastshoot-" + id + "-" + weapon.id, wtrc)){
|
||||
info.fastShots.getAndIncrement(weapon.id, 0, 1);
|
||||
|
||||
if(info.fastShots.get(weapon.id, 0) > (int)(wtrc / (weapon.getReload() / 2f)) + 8){
|
||||
kick(id, KickReason.kick);
|
||||
if(info.fastShots.get(weapon.id, 0) > (int)(wtrc / (weapon.getReload() / 2f)) + 30){
|
||||
kick(id, KickReason.fastShoot);
|
||||
}
|
||||
}else{
|
||||
info.fastShots.put(weapon.id, 0);
|
||||
@@ -202,6 +202,14 @@ public class NetServer extends Module{
|
||||
|
||||
if(recipe == null || recipe.debugOnly != debug) return;
|
||||
|
||||
Tile tile = world.tile(packet.x, packet.y);
|
||||
if(tile.synthetic() && admins.isValidateReplace() && !admins.validateBreak(admins.getTrace(Net.getConnection(id).address).uuid, Net.getConnection(id).address)){
|
||||
if(Timers.get("break-message-" + id, 120)){
|
||||
sendMessageTo(id, "[scarlet]Anti-grief: you are replacing blocks too quickly. wait until replacing again.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
state.inventory.removeItems(recipe.requirements);
|
||||
|
||||
Placement.placeBlock(placer.team, packet.x, packet.y, block, packet.rotation, true, false);
|
||||
@@ -221,6 +229,15 @@ public class NetServer extends Module{
|
||||
|
||||
if(!Placement.validBreak(placer.team, packet.x, packet.y)) return;
|
||||
|
||||
Tile tile = world.tile(packet.x, packet.y);
|
||||
|
||||
if(tile.synthetic() && !admins.validateBreak(admins.getTrace(Net.getConnection(id).address).uuid, Net.getConnection(id).address)){
|
||||
if(Timers.get("break-message-" + id, 120)){
|
||||
sendMessageTo(id, "[scarlet]Anti-grief: you are breaking blocks too quickly. wait until breaking again.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Block block = Placement.breakBlock(placer.team, packet.x, packet.y, true, false);
|
||||
|
||||
if(block != null) {
|
||||
@@ -282,6 +299,7 @@ public class NetServer extends Module{
|
||||
});
|
||||
|
||||
Net.handleServer(EntityRequestPacket.class, (cid, packet) -> {
|
||||
|
||||
int id = packet.id;
|
||||
int dest = cid;
|
||||
EntityGroup group = Entities.getGroup(packet.group);
|
||||
@@ -382,6 +400,12 @@ public class NetServer extends Module{
|
||||
return connections.get(connectionID).uuid;
|
||||
}
|
||||
|
||||
void sendMessageTo(int id, String message){
|
||||
ChatPacket packet = new ChatPacket();
|
||||
packet.text = message;
|
||||
Net.sendTo(id, packet, SendMode.tcp);
|
||||
}
|
||||
|
||||
void sync(){
|
||||
|
||||
if(timer.get(timerEntitySync, serverSyncTime)){
|
||||
|
||||
@@ -332,15 +332,15 @@ public class Renderer extends RendererModule{
|
||||
if(!player.isLocal && !player.isDead()){
|
||||
layout.setText(Core.font, player.name);
|
||||
Draw.color(0f, 0f, 0f, 0.3f);
|
||||
Draw.rect("blank", player.x, player.y + 8 - layout.height/2, layout.width + 2, layout.height + 2);
|
||||
Draw.rect("blank", player.getDrawPosition().x, player.getDrawPosition().y + 8 - layout.height/2, layout.width + 2, layout.height + 2);
|
||||
Draw.color();
|
||||
Draw.tcolor(player.getColor());
|
||||
Draw.text(player.name, player.x, player.y + 8);
|
||||
Draw.text(player.name, player.getDrawPosition().x, player.getDrawPosition().y + 8);
|
||||
|
||||
if(player.isAdmin){
|
||||
Draw.color(player.getColor());
|
||||
float s = 3f;
|
||||
Draw.rect("icon-admin-small", player.x + layout.width/2f + 2 + 1, player.y + 7f, s, s);
|
||||
Draw.rect("icon-admin-small", player.getDrawPosition().x + layout.width/2f + 2 + 1, player.getDrawPosition().y + 7f, s, s);
|
||||
}
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@@ -119,6 +119,8 @@ public abstract class SyncEntity extends DestructibleEntity{
|
||||
|
||||
time += 1f / spacing * Math.min(Timers.delta(), 1f);
|
||||
|
||||
time = Mathf.clamp(time, 0, 2f);
|
||||
|
||||
Mathf.lerp2(pos.set(last), target, time);
|
||||
|
||||
rotation = Mathf.slerpDelta(rotation, targetrot, 0.6f);
|
||||
|
||||
@@ -24,13 +24,14 @@ public class DefaultKeybinds {
|
||||
"dash", Input.SHIFT_LEFT,
|
||||
"rotate_alt", new Axis(Input.R, Input.E),
|
||||
"rotate", new Axis(Input.SCROLL),
|
||||
"toggle_menus", Input.C,
|
||||
"block_info", Input.CONTROL_LEFT,
|
||||
"player_list", Input.TAB,
|
||||
"item_withdraw", Input.SHIFT_LEFT,
|
||||
"chat", Input.ENTER,
|
||||
"chat_history_prev", Input.UP,
|
||||
"chat_history_next", Input.DOWN,
|
||||
"chat_scroll", new Axis(Input.SCROLL),
|
||||
"item_withdraw", Input.SHIFT_LEFT,
|
||||
"console", Input.GRAVE,
|
||||
"weapon_1", Input.NUM_1,
|
||||
"weapon_2", Input.NUM_2,
|
||||
@@ -41,7 +42,7 @@ public class DefaultKeybinds {
|
||||
);
|
||||
|
||||
KeyBinds.defaults(
|
||||
DeviceType.controller,
|
||||
DeviceType.controller,
|
||||
"move_x", new Axis(Input.CONTROLLER_L_STICK_HORIZONTAL_AXIS),
|
||||
"move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS),
|
||||
"cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS),
|
||||
|
||||
@@ -3,9 +3,13 @@ package io.anuke.mindustry.net;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Json;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
|
||||
public class Administration {
|
||||
public static final int defaultMaxBrokenBlocks = 15;
|
||||
public static final int defaultBreakCooldown = 1000*15;
|
||||
|
||||
private Json json = new Json();
|
||||
/**All player info. Maps UUIDs to info. This persists throughout restarts.*/
|
||||
private ObjectMap<String, PlayerInfo> playerInfo = new ObjectMap<>();
|
||||
@@ -14,12 +18,72 @@ public class Administration {
|
||||
private Array<String> bannedIPs = new Array<>();
|
||||
|
||||
public Administration(){
|
||||
Settings.defaults("playerInfo", "{}");
|
||||
Settings.defaults("bannedIPs", "{}");
|
||||
Settings.defaultList(
|
||||
"playerInfo", "{}",
|
||||
"bannedIPs", "{}",
|
||||
"antigrief", false,
|
||||
"antigrief-max", defaultMaxBrokenBlocks,
|
||||
"antigrief-cooldown", defaultBreakCooldown
|
||||
);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
public boolean isAntiGrief(){
|
||||
return Settings.getBool("antigrief");
|
||||
}
|
||||
|
||||
public boolean isValidateReplace(){
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAntiGrief(boolean antiGrief){
|
||||
Settings.putBool("antigrief", antiGrief);
|
||||
Settings.save();
|
||||
}
|
||||
|
||||
public void setAntiGriefParams(int maxBreak, int cooldown){
|
||||
Settings.putInt("antigrief-max", maxBreak);
|
||||
Settings.putInt("antigrief-cooldown", cooldown);
|
||||
Settings.save();
|
||||
}
|
||||
|
||||
public boolean validateBreak(String id, String ip){
|
||||
if(!isAntiGrief() || isAdmin(id, ip)) return true;
|
||||
|
||||
PlayerInfo info = getCreateInfo(id);
|
||||
|
||||
if(info.lastBroken == null || info.lastBroken.length != Settings.getInt("antigrief-max")){
|
||||
info.lastBroken = new long[Settings.getInt("antigrief-max")];
|
||||
}
|
||||
|
||||
long[] breaks = info.lastBroken;
|
||||
|
||||
int shiftBy = 0;
|
||||
for(int i = 0; i < breaks.length && breaks[i] != 0; i ++){
|
||||
if(TimeUtils.timeSinceMillis(breaks[i]) >= Settings.getInt("antigrief-cooldown")){
|
||||
shiftBy = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < breaks.length; i++) {
|
||||
breaks[i] = (i + shiftBy >= breaks.length) ? 0 : breaks[i + shiftBy];
|
||||
}
|
||||
|
||||
int remaining = 0;
|
||||
for(int i = 0; i < breaks.length; i ++){
|
||||
if(breaks[i] == 0){
|
||||
remaining = breaks.length - i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(remaining == 0) return false;
|
||||
|
||||
breaks[breaks.length - remaining] = TimeUtils.millis();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**Call when a player joins to update their information here.*/
|
||||
public void updatePlayerJoined(String id, String ip, String name){
|
||||
PlayerInfo info = getCreateInfo(id);
|
||||
@@ -248,6 +312,8 @@ public class Administration {
|
||||
public boolean banned, admin;
|
||||
public long lastKicked; //last kicked timestamp
|
||||
|
||||
public long[] lastBroken;
|
||||
|
||||
PlayerInfo(String id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ public class Packets {
|
||||
}
|
||||
}
|
||||
|
||||
public static class EntityShootPacket implements Packet{
|
||||
public static class EntityShootPacket implements Packet, UnimportantPacket{
|
||||
public float x, y, rotation;
|
||||
public short bulletid;
|
||||
public byte groupid;
|
||||
@@ -350,7 +350,7 @@ public class Packets {
|
||||
}
|
||||
|
||||
public enum KickReason{
|
||||
kick, invalidPassword, clientOutdated, serverOutdated, banned, gameover(true), recentKick, nameInUse, idInUse;
|
||||
kick, invalidPassword, clientOutdated, serverOutdated, banned, gameover(true), recentKick, nameInUse, idInUse, fastShoot;
|
||||
public final boolean quiet;
|
||||
|
||||
KickReason(){ quiet = false; }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Align;
|
||||
import io.anuke.ucore.function.Listenable;
|
||||
import io.anuke.ucore.scene.ui.TextButton;
|
||||
|
||||
@@ -27,7 +28,7 @@ public class MenuButton extends TextButton{
|
||||
|
||||
|
||||
table(t -> {
|
||||
t.add(text);
|
||||
t.add(text).wrap().growX().get().setAlignment(Align.center, Align.left);
|
||||
if(description != null){
|
||||
t.row();
|
||||
t.add(description).color(Color.LIGHT_GRAY);
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.badlogic.gdx.math.Interpolation;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Inputs;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.actions.Actions;
|
||||
@@ -26,11 +27,14 @@ import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class HudFragment implements Fragment{
|
||||
public final BlocksFragment blockfrag = new BlocksFragment();
|
||||
|
||||
private ImageButton menu, flip;
|
||||
private Table respawntable;
|
||||
private Table wavetable;
|
||||
private Label infolabel;
|
||||
private boolean shown = true;
|
||||
private float dsize = 58;
|
||||
private float isize = 40;
|
||||
|
||||
public void build(){
|
||||
|
||||
@@ -43,42 +47,25 @@ public class HudFragment implements Fragment{
|
||||
|
||||
new table() {{
|
||||
left();
|
||||
float dsize = 58;
|
||||
defaults().size(dsize).left();
|
||||
float isize = 40;
|
||||
|
||||
menu = new imagebutton("icon-menu", isize, ui.paused::show).get();
|
||||
flip = new imagebutton("icon-arrow-up", isize, () -> toggleMenus()).get();
|
||||
|
||||
flip = new imagebutton("icon-arrow-up", isize, () -> {
|
||||
if (wavetable.getActions().size != 0) return;
|
||||
|
||||
float dur = 0.3f;
|
||||
Interpolation in = Interpolation.pow3Out;
|
||||
|
||||
flip.getStyle().imageUp = Core.skin.getDrawable(shown ? "icon-arrow-down" : "icon-arrow-up");
|
||||
|
||||
if (shown) {
|
||||
blockfrag.toggle(false, dur, in);
|
||||
wavetable.actions(Actions.translateBy(0, wavetable.getHeight() + dsize, dur, in), Actions.call(() -> shown = false));
|
||||
infolabel.actions(Actions.translateBy(0, wavetable.getHeight(), dur, in), Actions.call(() -> shown = false));
|
||||
} else {
|
||||
shown = true;
|
||||
blockfrag.toggle(true, dur, in);
|
||||
wavetable.actions(Actions.translateBy(0, -wavetable.getTranslation().y, dur, in));
|
||||
infolabel.actions(Actions.translateBy(0, -infolabel.getTranslation().y, dur, in));
|
||||
update(t -> {
|
||||
if(Inputs.keyTap("toggle_menus") && !ui.chatfrag.chatOpen()){
|
||||
toggleMenus();
|
||||
}
|
||||
|
||||
}).get();
|
||||
});
|
||||
|
||||
new imagebutton("icon-pause", isize, () -> {
|
||||
if(mobile) DebugFragment.printDebugInfo();
|
||||
if (Net.active() && mobile) {
|
||||
if (Net.active()) {
|
||||
ui.listfrag.visible = !ui.listfrag.visible;
|
||||
} else {
|
||||
state.set(state.is(State.paused) ? State.playing : State.paused);
|
||||
}
|
||||
}).update(i -> {
|
||||
if (Net.active() && mobile) {
|
||||
if (Net.active()) {
|
||||
i.getStyle().imageUp = Core.skin.getDrawable("icon-players");
|
||||
} else {
|
||||
i.setDisabled(Net.active());
|
||||
@@ -209,6 +196,26 @@ public class HudFragment implements Fragment{
|
||||
blockfrag.build();
|
||||
}
|
||||
|
||||
private void toggleMenus(){
|
||||
if (wavetable.getActions().size != 0) return;
|
||||
|
||||
float dur = 0.3f;
|
||||
Interpolation in = Interpolation.pow3Out;
|
||||
|
||||
flip.getStyle().imageUp = Core.skin.getDrawable(shown ? "icon-arrow-down" : "icon-arrow-up");
|
||||
|
||||
if (shown) {
|
||||
blockfrag.toggle(false, dur, in);
|
||||
wavetable.actions(Actions.translateBy(0, wavetable.getHeight() + dsize, dur, in), Actions.call(() -> shown = false));
|
||||
infolabel.actions(Actions.translateBy(0, wavetable.getHeight(), dur, in), Actions.call(() -> shown = false));
|
||||
} else {
|
||||
shown = true;
|
||||
blockfrag.toggle(true, dur, in);
|
||||
wavetable.actions(Actions.translateBy(0, -wavetable.getTranslation().y, dur, in));
|
||||
infolabel.actions(Actions.translateBy(0, -infolabel.getTranslation().y, dur, in));
|
||||
}
|
||||
}
|
||||
|
||||
private String getEnemiesRemaining() {
|
||||
if(state.enemies == 1) {
|
||||
return Bundles.format("text.enemies.single", state.enemies);
|
||||
|
||||
@@ -64,7 +64,9 @@ public class PlayerListFragment implements Fragment{
|
||||
|
||||
update(t -> {
|
||||
if(!mobile){
|
||||
visible = Inputs.keyDown("player_list");
|
||||
if(Inputs.keyTap("player_list")){
|
||||
visible = !visible;
|
||||
}
|
||||
}
|
||||
if(!(Net.active() && !state.is(State.menu))){
|
||||
visible = false;
|
||||
|
||||
@@ -181,6 +181,11 @@ public class Tile implements Position{
|
||||
Block floor = floor();
|
||||
return isLinked() || !((floor.solid && (block == Blocks.air || block.solidifes)) || (block.solid && (!block.destructible && !block.update)));
|
||||
}
|
||||
|
||||
public boolean synthetic(){
|
||||
Block block = block();
|
||||
return block.update || block.destructible;
|
||||
}
|
||||
|
||||
public boolean solid(){
|
||||
Block block = block();
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import io.anuke.mindustry.resource.Liquid;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.types.LiquidBlock;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
|
||||
public class LiquidJunction extends LiquidBlock{
|
||||
@@ -30,10 +29,8 @@ public class LiquidJunction extends LiquidBlock{
|
||||
dir = (dir+4)%4;
|
||||
Tile to = tile.getNearby(dir);
|
||||
|
||||
Timers.run(20f, () -> {
|
||||
if(to.block().hasLiquids && to.block().acceptLiquid(to, tile, liquid, amount))
|
||||
to.block().handleLiquid(to, tile, liquid, amount);
|
||||
});
|
||||
if(to.block().hasLiquids && to.block().acceptLiquid(to, tile, liquid, amount))
|
||||
to.block().handleLiquid(to, tile, liquid, amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user