mirror of
https://github.com/Anuken/Mindustry.git
synced 2024-09-21 05:17:50 +03:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
9bfb5216f9
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user