Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -201,6 +201,7 @@ project(":core"){
|
|||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
task preGen{
|
task preGen{
|
||||||
|
outputs.upToDateWhen{ false }
|
||||||
generateLocales()
|
generateLocales()
|
||||||
writeVersion()
|
writeVersion()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,14 +242,13 @@ public class BlockIndexer{
|
|||||||
int quadrantY = tile.y / quadrantSize;
|
int quadrantY = tile.y / quadrantSize;
|
||||||
itemSet.clear();
|
itemSet.clear();
|
||||||
|
|
||||||
Tile rounded = world.tile(Mathf.clamp(quadrantX * quadrantSize + quadrantSize / 2, 0, world.width() - 1),
|
Tile rounded = world.tile(Mathf.clamp(quadrantX * quadrantSize + quadrantSize / 2, 0, world.width() - 1), Mathf.clamp(quadrantY * quadrantSize + quadrantSize / 2, 0, world.height() - 1));
|
||||||
Mathf.clamp(quadrantY * quadrantSize + quadrantSize / 2, 0, world.height() - 1));
|
|
||||||
|
|
||||||
//find all items that this quadrant contains
|
//find all items that this quadrant contains
|
||||||
for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){
|
for(int x = Math.max(0, rounded.x - quadrantSize / 2); x < rounded.x + quadrantSize / 2 && x < world.width(); x++){
|
||||||
for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){
|
for(int y = Math.max(0, rounded.y - quadrantSize / 2); y < rounded.y + quadrantSize / 2 && y < world.height(); y++){
|
||||||
Tile result = world.tile(x, y);
|
Tile result = world.tile(x, y);
|
||||||
if(result == null || result.drop() == null || !scanOres.contains(result.drop())) continue;
|
if(result == null || result.drop() == null || !scanOres.contains(result.drop()) || result.block() != Blocks.air) continue;
|
||||||
|
|
||||||
itemSet.add(result.drop());
|
itemSet.add(result.drop());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
|||||||
import io.anuke.mindustry.entities.traits.Entity;
|
import io.anuke.mindustry.entities.traits.Entity;
|
||||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||||
import io.anuke.mindustry.entities.type.Player;
|
import io.anuke.mindustry.entities.type.Player;
|
||||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.Version;
|
import io.anuke.mindustry.game.Version;
|
||||||
import io.anuke.mindustry.gen.Call;
|
import io.anuke.mindustry.gen.Call;
|
||||||
@@ -185,6 +185,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
sendWorldData(player, id);
|
sendWorldData(player, id);
|
||||||
|
|
||||||
platform.updateRPC();
|
platform.updateRPC();
|
||||||
|
|
||||||
|
Events.fire(new PlayerJoin(player));
|
||||||
});
|
});
|
||||||
|
|
||||||
Net.handleServer(InvokePacket.class, (id, packet) -> {
|
Net.handleServer(InvokePacket.class, (id, packet) -> {
|
||||||
@@ -228,25 +230,34 @@ public class NetServer implements ApplicationListener{
|
|||||||
});
|
});
|
||||||
|
|
||||||
//duration of a a kick in seconds
|
//duration of a a kick in seconds
|
||||||
int kickDuration = 10 * 60;
|
int kickDuration = 15 * 60;
|
||||||
|
|
||||||
class VoteSession{
|
class VoteSession{
|
||||||
Player target;
|
Player target;
|
||||||
ObjectSet<String> voted = new ObjectSet<>();
|
ObjectSet<String> voted = new ObjectSet<>();
|
||||||
ObjectMap<Player, VoteSession> map;
|
VoteSession[] map;
|
||||||
Timer.Task task;
|
Timer.Task task;
|
||||||
int votes;
|
int votes;
|
||||||
|
|
||||||
public VoteSession(ObjectMap<Player, VoteSession> map, Player target){
|
public VoteSession(VoteSession[] map, Player target){
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.task = Timer.schedule(() -> {
|
this.task = Timer.schedule(() -> {
|
||||||
if(!checkPass()){
|
if(!checkPass()){
|
||||||
Call.sendMessage(Strings.format("[lightgray]Vote failed. Not enough votes to kick[orange] {0}[lightgray].", target.name));
|
Call.sendMessage(Strings.format("[lightgray]Vote failed. Not enough votes to kick[orange] {0}[lightgray].", target.name));
|
||||||
|
map[0] = null;
|
||||||
|
task.cancel();
|
||||||
}
|
}
|
||||||
map.remove(target);
|
}, 60 * 1);
|
||||||
task.cancel();
|
}
|
||||||
}, 60 * 1.5f);
|
|
||||||
|
void vote(Player player, int d){
|
||||||
|
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.",
|
||||||
|
player.name, target.name, votes, votesRequired()));
|
||||||
|
//checkPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkPass(){
|
boolean checkPass(){
|
||||||
@@ -254,6 +265,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
Call.sendMessage(Strings.format("[orange]Vote passed.[scarlet] {0}[orange] will be kicked from the server.", target.name));
|
Call.sendMessage(Strings.format("[orange]Vote passed.[scarlet] {0}[orange] will be kicked from the server.", target.name));
|
||||||
admins.getInfo(target.uuid).lastKicked = Time.millis() + kickDuration*1000;
|
admins.getInfo(target.uuid).lastKicked = Time.millis() + kickDuration*1000;
|
||||||
kick(target.con.id, KickReason.vote);
|
kick(target.con.id, KickReason.vote);
|
||||||
|
map[0] = null;
|
||||||
|
task.cancel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -261,10 +274,10 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//cooldown between votes
|
//cooldown between votes
|
||||||
int voteTime = 60 * 10;
|
int voteTime = 60 * 5;
|
||||||
Timekeeper vtime = new Timekeeper(voteTime);
|
Timekeeper vtime = new Timekeeper(voteTime);
|
||||||
//current kick sessions
|
//current kick sessions
|
||||||
ObjectMap<Player, VoteSession> currentlyKicking = new ObjectMap<>();
|
VoteSession[] currentlyKicking = {null};
|
||||||
|
|
||||||
clientCommands.<Player>register("votekick", "[player...]", "Vote to kick a player, with a cooldown.", (args, player) -> {
|
clientCommands.<Player>register("votekick", "[player...]", "Vote to kick a player, with a cooldown.", (args, player) -> {
|
||||||
if(playerGroup.size() < 3){
|
if(playerGroup.size() < 3){
|
||||||
@@ -272,8 +285,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(currentlyKicking.values().toArray().contains(v -> v.voted.contains(player.uuid) || v.voted.contains(admins.getInfo(player.uuid).lastIP))){
|
if(player.isLocal){
|
||||||
player.sendMessage("[scarlet]You've already voted. Sit down.");
|
player.sendMessage("[scarlet]Just kick them yourself if you're the host.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,24 +309,20 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(found != null){
|
if(found != null){
|
||||||
if(player == found){
|
if(found.isAdmin){
|
||||||
player.sendMessage("[scarlet]If you're interested in kicking yourself, just leave.");
|
|
||||||
}else if(found.isAdmin){
|
|
||||||
player.sendMessage("[scarlet]Did you really expect to be able to kick an admin?");
|
player.sendMessage("[scarlet]Did you really expect to be able to kick an admin?");
|
||||||
|
}else if(found.isLocal){
|
||||||
|
player.sendMessage("[scarlet]Local players cannot be kicked.");
|
||||||
}else{
|
}else{
|
||||||
if(!currentlyKicking.containsKey(found) && !vtime.get()){
|
if(!vtime.get()){
|
||||||
player.sendMessage("[scarlet]You must wait " + voteTime/60 + " minutes between votekicks.");
|
player.sendMessage("[scarlet]You must wait " + voteTime/60 + " minutes between votekicks.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VoteSession session = currentlyKicking.getOr(found, () -> new VoteSession(currentlyKicking, found));
|
VoteSession session = new VoteSession(currentlyKicking, found);
|
||||||
session.votes ++;
|
session.vote(player, 1);
|
||||||
session.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] /votekick #{4}[] to agree.",
|
|
||||||
player.name, found.name, session.votes, votesRequired(), found.con.id));
|
|
||||||
session.checkPass();
|
|
||||||
vtime.reset();
|
vtime.reset();
|
||||||
|
currentlyKicking[0] = session;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
player.sendMessage("[scarlet]No player[orange]'" + args[0] + "'[scarlet] found.");
|
player.sendMessage("[scarlet]No player[orange]'" + args[0] + "'[scarlet] found.");
|
||||||
@@ -321,6 +330,31 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
clientCommands.<Player>register("vote", "<y/n>", "Vote to kick the current player.", (arg, player) -> {
|
||||||
|
if(currentlyKicking[0] == null){
|
||||||
|
player.sendMessage("[scarlet]Nobody is being voted on.");
|
||||||
|
}else{
|
||||||
|
if(currentlyKicking[0].voted.contains(player.uuid) || currentlyKicking[0].voted.contains(admins.getInfo(player.uuid).lastIP)){
|
||||||
|
player.sendMessage("[scarlet]You've already voted. Sit down.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currentlyKicking[0].target == player){
|
||||||
|
player.sendMessage("[scarlet]You can't vote on your own trial.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!arg[0].toLowerCase().equals("y") && !arg[0].toLowerCase().equals("n")){
|
||||||
|
player.sendMessage("[scarlet]Vote either 'y' (yes) or 'n' (no).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sign = arg[0].toLowerCase().equals("y") ? 1 : -1;
|
||||||
|
currentlyKicking[0].vote(player, sign);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
clientCommands.<Player>register("sync", "Re-synchronize world state.", (args, player) -> {
|
clientCommands.<Player>register("sync", "Re-synchronize world state.", (args, player) -> {
|
||||||
if(player.isLocal){
|
if(player.isLocal){
|
||||||
player.sendMessage("[scarlet]Re-synchronizing as the host is pointless.");
|
player.sendMessage("[scarlet]Re-synchronizing as the host is pointless.");
|
||||||
@@ -332,7 +366,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int votesRequired(){
|
public int votesRequired(){
|
||||||
return playerGroup.size() * 2 / 3;
|
return 2 + (playerGroup.size() > 4 ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Team assignTeam(Player current, Iterable<Player> players){
|
public Team assignTeam(Player current, Iterable<Player> players){
|
||||||
@@ -370,6 +404,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(player.con.hasConnected){
|
if(player.con.hasConnected){
|
||||||
|
Events.fire(new PlayerLeave(player));
|
||||||
Call.sendMessage("[accent]" + player.name + "[accent] has disconnected.");
|
Call.sendMessage("[accent]" + player.name + "[accent] has disconnected.");
|
||||||
Call.onPlayerDisconnect(player.id);
|
Call.onPlayerDisconnect(player.id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
//visual only.
|
//visual only.
|
||||||
if(Net.client()){
|
if(Net.client()){
|
||||||
Tile tile = world.tile(unit.spawner);
|
Tile tile = world.tile(unit.spawner);
|
||||||
if(tile != null && !Net.client()){
|
if(tile != null){
|
||||||
tile.block().unitRemoved(tile, unit);
|
tile.block().unitRemoved(tile, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||||
public static final int timerSync = 2;
|
public static final int timerSync = 2;
|
||||||
public static final int timerAbility = 3;
|
public static final int timerAbility = 3;
|
||||||
|
public static final int timerTransfer = 4;
|
||||||
private static final int timerShootLeft = 0;
|
private static final int timerShootLeft = 0;
|
||||||
private static final int timerShootRight = 1;
|
private static final int timerShootRight = 1;
|
||||||
private static final float liftoffBoost = 0.2f;
|
private static final float liftoffBoost = 0.2f;
|
||||||
@@ -59,7 +60,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
|
|
||||||
public NetConnection con;
|
public NetConnection con;
|
||||||
public boolean isLocal = false;
|
public boolean isLocal = false;
|
||||||
public Interval timer = new Interval(4);
|
public Interval timer = new Interval(6);
|
||||||
public TargetTrait target;
|
public TargetTrait target;
|
||||||
public TargetTrait moveTarget;
|
public TargetTrait moveTarget;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import io.anuke.mindustry.entities.traits.BuilderTrait;
|
|||||||
import io.anuke.mindustry.entities.type.Unit;
|
import io.anuke.mindustry.entities.type.Unit;
|
||||||
import io.anuke.mindustry.type.Zone;
|
import io.anuke.mindustry.type.Zone;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.mindustry.entities.type.Player;
|
||||||
|
|
||||||
public class EventType{
|
public class EventType{
|
||||||
|
|
||||||
@@ -184,5 +185,22 @@ public class EventType{
|
|||||||
public static class ResizeEvent{
|
public static class ResizeEvent{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class PlayerJoin{
|
||||||
|
public final Player player;
|
||||||
|
|
||||||
|
public PlayerJoin(Player player){
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PlayerLeave{
|
||||||
|
public final Player player;
|
||||||
|
|
||||||
|
public PlayerLeave(Player player){
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
|
|
||||||
/** Controls playback of multiple music tracks.*/
|
/** Controls playback of multiple music tracks.*/
|
||||||
public class MusicControl{
|
public class MusicControl{
|
||||||
private static final float finTime = 120f, foutTime = 120f, musicInterval = 60 * 60 * 3f, musicChance = 0.5f, musicWaveChance = 0.4f;
|
private static final float finTime = 120f, foutTime = 120f, musicInterval = 60 * 60 * 3f, musicChance = 0.6f, musicWaveChance = 0.5f;
|
||||||
|
|
||||||
/** normal, ambient music, plays at any time */
|
/** normal, ambient music, plays at any time */
|
||||||
public final Array<Music> ambientMusic = Array.with(Musics.game1, Musics.game3, Musics.game4, Musics.game6);
|
public final Array<Music> ambientMusic = Array.with(Musics.game1, Musics.game3, Musics.game4, Musics.game6);
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
|
|
||||||
@Remote(targets = Loc.both, forward = true, called = Loc.server)
|
@Remote(targets = Loc.both, forward = true, called = Loc.server)
|
||||||
public static void transferInventory(Player player, Tile tile){
|
public static void transferInventory(Player player, Tile tile){
|
||||||
if(Net.server() && (player.item().amount <= 0 || player.isTransferring)){
|
if(Net.server() && (player.item().amount <= 0 || player.isTransferring || !player.timer.get(Player.timerTransfer, 40))){
|
||||||
throw new ValidateException(player, "Player cannot transfer an item.");
|
throw new ValidateException(player, "Player cannot transfer an item.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ public abstract class InputHandler implements InputProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void tryDropItems(Tile tile, float x, float y){
|
public void tryDropItems(Tile tile, float x, float y){
|
||||||
if(!droppingItem || player.item().amount <= 0 || canTapPlayer(x, y) || state.isPaused()){
|
if(!droppingItem || player.item().amount <= 0 || canTapPlayer(x, y) || state.isPaused() || !player.timer.check(Player.timerTransfer, 40)){
|
||||||
droppingItem = false;
|
droppingItem = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class MapsDialog extends FloatingDialog{
|
|||||||
String name = map.tags.getOr("name", () -> {
|
String name = map.tags.getOr("name", () -> {
|
||||||
String result = "unknown";
|
String result = "unknown";
|
||||||
int number = 0;
|
int number = 0;
|
||||||
while(maps.byName(result + number++) != null) ;
|
while(maps.byName(result + number++) != null);
|
||||||
return result + number;
|
return result + number;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class BlockInventoryFragment extends Fragment{
|
|||||||
|
|
||||||
@Remote(called = Loc.server, targets = Loc.both, forward = true)
|
@Remote(called = Loc.server, targets = Loc.both, forward = true)
|
||||||
public static void requestItem(Player player, Tile tile, Item item, int amount){
|
public static void requestItem(Player player, Tile tile, Item item, int amount){
|
||||||
if(player == null || tile == null) return;
|
if(player == null || tile == null || !player.timer.get(Player.timerTransfer, 20)) return;
|
||||||
|
|
||||||
int removed = tile.block().removeStack(tile, item, amount);
|
int removed = tile.block().removeStack(tile, item, amount);
|
||||||
|
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ public class Block extends BlockStorage{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Damage.dynamicExplosion(x, y, flammability, explosiveness, power, tilesize * size / 2f, Pal.darkFlame);
|
Damage.dynamicExplosion(x, y, flammability, explosiveness * 3.5f, power, tilesize * size / 2f, Pal.darkFlame);
|
||||||
if(!tile.floor().solid && !tile.floor().isLiquid){
|
if(!tile.floor().solid && !tile.floor().isLiquid){
|
||||||
RubbleDecal.create(tile.drawx(), tile.drawy(), size);
|
RubbleDecal.create(tile.drawx(), tile.drawy(), size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
|||||||
protected Effects.Effect explodeEffect = Fx.generatespark;
|
protected Effects.Effect explodeEffect = Fx.generatespark;
|
||||||
protected Color heatColor = Color.valueOf("ff9b59");
|
protected Color heatColor = Color.valueOf("ff9b59");
|
||||||
protected TextureRegion topRegion, liquidRegion;
|
protected TextureRegion topRegion, liquidRegion;
|
||||||
protected boolean randomlyExplode = false;
|
protected boolean randomlyExplode = true;
|
||||||
|
|
||||||
public ItemLiquidGenerator(boolean hasItems, boolean hasLiquids, String name){
|
public ItemLiquidGenerator(boolean hasItems, boolean hasLiquids, String name){
|
||||||
super(name);
|
super(name);
|
||||||
@@ -127,8 +127,10 @@ public class ItemLiquidGenerator extends PowerGenerator{
|
|||||||
|
|
||||||
if(randomlyExplode && Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.5f))){
|
if(randomlyExplode && Mathf.chance(entity.delta() * 0.06 * Mathf.clamp(entity.explosiveness - 0.5f))){
|
||||||
//this block is run last so that in the event of a block destruction, no code relies on the block type
|
//this block is run last so that in the event of a block destruction, no code relies on the block type
|
||||||
entity.damage(Mathf.random(11f));
|
Core.app.post(() -> {
|
||||||
Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f));
|
entity.damage(Mathf.random(11f));
|
||||||
|
Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
entity.productionEfficiency = 0.0f;
|
entity.productionEfficiency = 0.0f;
|
||||||
|
|||||||
Reference in New Issue
Block a user