Implemented authoritative movement/shooting, fixed netbugs

This commit is contained in:
Anuken
2018-06-13 17:06:46 -04:00
parent 4ca9a26bdd
commit c077f6e1e8
17 changed files with 268 additions and 87 deletions
@@ -18,6 +18,7 @@ import io.anuke.mindustry.gen.CallEntity;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.graphics.Trail;
import io.anuke.mindustry.net.In;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
@@ -28,10 +29,7 @@ import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.entities.trait.SolidTrait;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.ThreadQueue;
import io.anuke.ucore.util.Timer;
import io.anuke.ucore.util.*;
import java.io.DataInput;
import java.io.DataOutput;
@@ -40,10 +38,7 @@ import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
public class Player extends Unit implements BuilderTrait, CarryTrait {
private static final float walkSpeed = 1.1f;
private static final float flySpeed = 0.4f;
private static final float flyMaxSpeed = 3f;
private static final float dashSpeed = 1.8f;
private static final float debugSpeed = 1.8f;
private static final Vector2 movement = new Vector2();
public static int typeID = -1;
@@ -56,9 +51,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
public float baseRotation;
public float pointerX, pointerY;
public String name = "name";
public String uuid;
public boolean isAdmin, isTransferring;
public boolean isAdmin, isTransferring, isShooting;
public Color color = new Color();
public Array<Upgrade> upgrades = new Array<>();
@@ -224,7 +220,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
@Override
public void removed() {
dropCarry();
dropCarryLocal();
}
@Override
@@ -388,8 +384,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
if(isDead()){
CoreEntity entity = (CoreEntity)getClosestCore();
if(!respawning && entity != null && entity.trySetPlayer(this)){
respawning = true;
if (!respawning && entity != null) {
entity.trySetPlayer(this);
}
return;
}
@@ -398,6 +394,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
interpolate();
updateBuilding(this); //building happens even with non-locals
status.update(this); //status effect updating also happens with non locals for effect purposes
if(Net.server()){
updateShooting(); //server simulates player shooting
}
return;
}
@@ -424,13 +424,13 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
Tile tile = world.tileWorld(x, y);
//if player is in solid block
if(tile != null && tile.solid()) {
if(tile != null && tile.solid() && !noclip) {
damage(health + 1); //die instantly
}
if(ui.chatfrag.chatOpen()) return;
float speed = Inputs.keyDown("dash") ? (debug ? Player.dashSpeed * 5f : Player.dashSpeed) : Player.walkSpeed;
float speed = Inputs.keyDown("dash") && debug ? 5f : mech.speed;
float carrySlowdown = 0.3f;
speed *= ((1f-carrySlowdown) + (inventory.hasItem() ? (float)inventory.getItem().amount/inventory.capacity(): 1f) * carrySlowdown);
@@ -452,16 +452,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
movement.y += ya*speed;
movement.x += xa*speed;
boolean shooting = isShooting();
if(shooting){
Vector2 vec = Graphics.world(Vars.control.input(playerIndex).getMouseX(),
Vars.control.input(playerIndex).getMouseY());
float vx = vec.x, vy = vec.y;
weapon.update(this, true, vx, vy);
weapon.update(this, false, vx, vy);
}
Vector2 vec = Graphics.world(Vars.control.input(playerIndex).getMouseX(),
Vars.control.input(playerIndex).getMouseY());
pointerX = vec.x;
pointerY = vec.y;
updateShooting();
movement.limit(speed);
@@ -474,7 +469,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
baseRotation = Mathf.slerpDelta(baseRotation, movement.angle(), 0.13f);
}
if(!shooting){
if(!isShooting()){
if(!movement.isZero()) {
rotation = Mathf.slerpDelta(rotation, movement.angle(), 0.13f);
}
@@ -484,6 +479,13 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
}
}
protected void updateShooting(){
if(isShooting()){
weapon.update(this, true, pointerX, pointerY);
weapon.update(this, false, pointerX, pointerY);
}
}
protected void updateFlying(){
if(Units.invalidateTarget(target, this)){
target = null;
@@ -506,7 +508,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
pickupTarget = null;
}
movement.set(targetX - x, targetY - y).limit(flySpeed);
movement.set(targetX - x, targetY - y).limit(mech.speed);
movement.setAngle(Mathf.slerpDelta(movement.angle(), velocity.angle(), 0.05f));
if(distanceTo(targetX, targetY) < attractDst){
@@ -514,7 +516,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
}
velocity.add(movement);
updateVelocityStatus(0.1f, flyMaxSpeed);
updateVelocityStatus(0.1f, mech.maxSpeed);
//hovering effect
x += Mathf.sin(Timers.time() + id * 999, 25f, 0.08f);
@@ -531,7 +533,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
//autofire: mobile only!
if(mobile) {
boolean lastShooting = isShooting;
if (target == null) {
isShooting = false;
target = Units.getClosestTarget(team, x, y, inventory.getAmmoRange());
} else {
//rotate toward and shoot the target
@@ -540,16 +545,24 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
Vector2 intercept =
Predict.intercept(x, y, target.getX(), target.getY(), target.getVelocity().x - velocity.x, target.getVelocity().y - velocity.y, inventory.getAmmo().bullet.speed);
weapon.update(this, true, intercept.x, intercept.y);
weapon.update(this, false, intercept.x, intercept.y);
pointerX = intercept.x;
pointerY = intercept.y;
updateShooting();
isShooting = true;
}
//update status of shooting to server
if(lastShooting != isShooting){
CallEntity.setShooting(isShooting);
}
}else if(isShooting()){ //desktop shooting, TODO
Vector2 vec = Graphics.world(Vars.control.input(playerIndex).getMouseX(),
Vars.control.input(playerIndex).getMouseY());
float vx = vec.x, vy = vec.y;
pointerX = vec.x;
pointerY = vec.y;
weapon.update(this, true, vx, vy);
weapon.update(this, false, vx, vy);
updateShooting();
}
}
}
@@ -578,7 +591,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
}
public boolean isShooting(){
return control.input(playerIndex).canShoot() && control.input(playerIndex).isShooting() && inventory.hasAmmo();
return isShooting && inventory.hasAmmo();
}
public void setRespawning(){
respawning = true;
}
@Override
@@ -601,7 +618,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
if(isLocal){
stream.writeInt(playerIndex);
super.writeSave(stream);
super.writeSave(stream, false);
stream.writeByte(upgrades.size);
for(Upgrade u : upgrades){
@@ -632,7 +649,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
@Override
public void write(DataOutput buffer) throws IOException {
super.writeSave(buffer);
super.writeSave(buffer, !isLocal);
buffer.writeUTF(name);
buffer.writeInt(Color.rgba8888(color));
buffer.writeBoolean(dead);
+14 -10
View File
@@ -105,16 +105,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
@Override
public void writeSave(DataOutput stream) throws IOException {
stream.writeByte(team.ordinal());
stream.writeFloat(x);
stream.writeFloat(y);
stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
stream.writeByte((byte)(Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
stream.writeShort((short)(rotation*2));
stream.writeShort((short)health);
stream.writeByte(status.current().id);
stream.writeShort((short)(status.getTime()*2));
inventory.write(stream);
writeSave(stream, false);
}
@Override
@@ -139,6 +130,19 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
this.status.set(StatusEffect.getByID(effect), etime);
}
public void writeSave(DataOutput stream, boolean net) throws IOException {
stream.writeByte(team.ordinal());
stream.writeFloat(net ? interpolator.target.x : x);
stream.writeFloat(net ? interpolator.target.y : y);
stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
stream.writeByte((byte)(Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
stream.writeShort((short)(rotation*2));
stream.writeShort((short)health);
stream.writeByte(status.current().id);
stream.writeShort((short)(status.getTime()*2));
inventory.write(stream);
}
public StatusEffect getStatus(){
return status.current();
}
@@ -1,6 +1,11 @@
package io.anuke.mindustry.entities.traits;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.mindustry.content.fx.UnitFx;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.gen.CallEntity;
import io.anuke.mindustry.net.In;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.entities.trait.SolidTrait;
@@ -17,23 +22,36 @@ public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{
carry(null);
}
default void dropCarryLocal(){
setCarryOf(null, this, null);
}
/**Do not override unless absolutely necessary.
* Carries a unit. To drop a unit, call with {@code null}.*/
default void carry(CarriableTrait unit){
if(getCarry() != null){ //already carrying something, drop it
CallEntity.setCarryOf(this instanceof Player ? (Player)this : null, this, unit);
}
@Remote(called = Loc.server, targets = Loc.both, forward = true, in = In.entities)
static void setCarryOf(Player player, CarryTrait trait, CarriableTrait unit){
if(player != null){ //when a server recieves this called from a player, set the carrier to the player.
trait = player;
}
if(trait.getCarry() != null){ //already carrying something, drop it
//drop current
Effects.effect(UnitFx.unitDrop, getCarry());
getCarry().setCarrier(null);
setCarry(null);
Effects.effect(UnitFx.unitDrop, trait.getCarry());
trait.getCarry().setCarrier(null);
trait.setCarry(null);
if(unit != null){
carry(unit); //now carry this new thing
trait.carry(unit); //now carry this new thing
}
}else if(unit != null){ //not currently carrying anything, make sure it's not null
setCarry(unit);
unit.setCarrier(this);
trait.setCarry(unit);
unit.setCarrier(trait);
Effects.effect(UnitFx.unitPickup, this);
Effects.effect(UnitFx.unitPickup, trait);
}
}
}