1
0
mirror of https://github.com/Anuken/Mindustry.git synced 2024-09-21 13:28:12 +03:00

Merge remote-tracking branch 'origin/master'

This commit is contained in:
Anuken 2019-09-02 20:59:44 -04:00
commit 9bfb5216f9
12 changed files with 99 additions and 43 deletions

View File

@ -201,6 +201,7 @@ project(":core"){
apply plugin: "java"
task preGen{
outputs.upToDateWhen{ false }
generateLocales()
writeVersion()
}
@ -321,4 +322,4 @@ task deployAll{
dependsOn "desktop:packrMacOS"
dependsOn "server:deploy"
dependsOn "android:deploy"
}
}

View File

@ -242,14 +242,13 @@ public class BlockIndexer{
int quadrantY = tile.y / quadrantSize;
itemSet.clear();
Tile rounded = world.tile(Mathf.clamp(quadrantX * quadrantSize + quadrantSize / 2, 0, world.width() - 1),
Mathf.clamp(quadrantY * quadrantSize + quadrantSize / 2, 0, world.height() - 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));
//find all items that this quadrant contains
for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){
for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){
for(int x = Math.max(0, rounded.x - quadrantSize / 2); x < rounded.x + quadrantSize / 2 && x < world.width(); x++){
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);
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());
}

View File

@ -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.SyncTrait;
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.Version;
import io.anuke.mindustry.gen.Call;
@ -74,7 +74,7 @@ public class NetServer implements ApplicationListener{
});
Net.handleServer(Disconnect.class, (id, packet) -> {
Player player = connections.get(id);
Player player = connections.get(id);
if(player != null){
onDisconnect(player, packet.reason);
}
@ -185,6 +185,8 @@ public class NetServer implements ApplicationListener{
sendWorldData(player, id);
platform.updateRPC();
Events.fire(new PlayerJoin(player));
});
Net.handleServer(InvokePacket.class, (id, packet) -> {
@ -228,25 +230,34 @@ public class NetServer implements ApplicationListener{
});
//duration of a a kick in seconds
int kickDuration = 10 * 60;
int kickDuration = 15 * 60;
class VoteSession{
Player target;
ObjectSet<String> voted = new ObjectSet<>();
ObjectMap<Player, VoteSession> map;
VoteSession[] map;
Timer.Task task;
int votes;
public VoteSession(ObjectMap<Player, VoteSession> map, Player target){
public VoteSession(VoteSession[] map, Player target){
this.target = target;
this.map = map;
this.task = Timer.schedule(() -> {
if(!checkPass()){
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);
task.cancel();
}, 60 * 1.5f);
}, 60 * 1);
}
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(){
@ -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));
admins.getInfo(target.uuid).lastKicked = Time.millis() + kickDuration*1000;
kick(target.con.id, KickReason.vote);
map[0] = null;
task.cancel();
return true;
}
return false;
@ -261,10 +274,10 @@ public class NetServer implements ApplicationListener{
}
//cooldown between votes
int voteTime = 60 * 10;
int voteTime = 60 * 5;
Timekeeper vtime = new Timekeeper(voteTime);
//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) -> {
if(playerGroup.size() < 3){
@ -272,8 +285,8 @@ public class NetServer implements ApplicationListener{
return;
}
if(currentlyKicking.values().toArray().contains(v -> v.voted.contains(player.uuid) || v.voted.contains(admins.getInfo(player.uuid).lastIP))){
player.sendMessage("[scarlet]You've already voted. Sit down.");
if(player.isLocal){
player.sendMessage("[scarlet]Just kick them yourself if you're the host.");
return;
}
@ -296,24 +309,20 @@ public class NetServer implements ApplicationListener{
}
if(found != null){
if(player == found){
player.sendMessage("[scarlet]If you're interested in kicking yourself, just leave.");
}else if(found.isAdmin){
if(found.isAdmin){
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{
if(!currentlyKicking.containsKey(found) && !vtime.get()){
if(!vtime.get()){
player.sendMessage("[scarlet]You must wait " + voteTime/60 + " minutes between votekicks.");
return;
}
VoteSession session = currentlyKicking.getOr(found, () -> new VoteSession(currentlyKicking, found));
session.votes ++;
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();
VoteSession session = new VoteSession(currentlyKicking, found);
session.vote(player, 1);
vtime.reset();
currentlyKicking[0] = session;
}
}else{
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) -> {
if(player.isLocal){
player.sendMessage("[scarlet]Re-synchronizing as the host is pointless.");
@ -332,7 +366,7 @@ public class NetServer implements ApplicationListener{
}
public int votesRequired(){
return playerGroup.size() * 2 / 3;
return 2 + (playerGroup.size() > 4 ? 1 : 0);
}
public Team assignTeam(Player current, Iterable<Player> players){
@ -370,8 +404,9 @@ public class NetServer implements ApplicationListener{
}
if(player.con.hasConnected){
Events.fire(new PlayerLeave(player));
Call.sendMessage("[accent]" + player.name + "[accent] has disconnected.");
Call.onPlayerDisconnect(player.id);
Call.onPlayerDisconnect(player.id);
}
player.remove();
netServer.connections.remove(player.con.id);

View File

@ -58,7 +58,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
//visual only.
if(Net.client()){
Tile tile = world.tile(unit.spawner);
if(tile != null && !Net.client()){
if(tile != null){
tile.block().unitRemoved(tile, unit);
}

View File

@ -37,6 +37,7 @@ import static io.anuke.mindustry.Vars.*;
public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
public static final int timerSync = 2;
public static final int timerAbility = 3;
public static final int timerTransfer = 4;
private static final int timerShootLeft = 0;
private static final int timerShootRight = 1;
private static final float liftoffBoost = 0.2f;
@ -59,7 +60,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
public NetConnection con;
public boolean isLocal = false;
public Interval timer = new Interval(4);
public Interval timer = new Interval(6);
public TargetTrait target;
public TargetTrait moveTarget;

View File

@ -5,6 +5,7 @@ import io.anuke.mindustry.entities.traits.BuilderTrait;
import io.anuke.mindustry.entities.type.Unit;
import io.anuke.mindustry.type.Zone;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.entities.type.Player;
public class EventType{
@ -184,5 +185,22 @@ public class EventType{
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;
}
}
}

View File

@ -14,7 +14,7 @@ import static io.anuke.mindustry.Vars.*;
/** Controls playback of multiple music tracks.*/
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 */
public final Array<Music> ambientMusic = Array.with(Musics.game1, Musics.game3, Musics.game4, Musics.game6);

View File

@ -59,7 +59,7 @@ public abstract class InputHandler implements InputProcessor{
@Remote(targets = Loc.both, forward = true, called = Loc.server)
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.");
}
@ -288,7 +288,7 @@ public abstract class InputHandler implements InputProcessor{
}
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;
return;
}

View File

@ -80,7 +80,7 @@ public class MapsDialog extends FloatingDialog{
String name = map.tags.getOr("name", () -> {
String result = "unknown";
int number = 0;
while(maps.byName(result + number++) != null) ;
while(maps.byName(result + number++) != null);
return result + number;
});

View File

@ -40,7 +40,7 @@ public class BlockInventoryFragment extends Fragment{
@Remote(called = Loc.server, targets = Loc.both, forward = true)
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);

View File

@ -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){
RubbleDecal.create(tile.drawx(), tile.drawy(), size);
}

View File

@ -37,7 +37,7 @@ public class ItemLiquidGenerator extends PowerGenerator{
protected Effects.Effect explodeEffect = Fx.generatespark;
protected Color heatColor = Color.valueOf("ff9b59");
protected TextureRegion topRegion, liquidRegion;
protected boolean randomlyExplode = false;
protected boolean randomlyExplode = true;
public ItemLiquidGenerator(boolean hasItems, boolean hasLiquids, String 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))){
//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));
Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f));
Core.app.post(() -> {
entity.damage(Mathf.random(11f));
Effects.effect(explodeEffect, tile.worldx() + Mathf.range(size * tilesize / 2f), tile.worldy() + Mathf.range(size * tilesize / 2f));
});
}
}else{
entity.productionEfficiency = 0.0f;