This commit is contained in:
Anuken 2020-12-05 20:48:56 -05:00
parent d61bb66418
commit f9cfc8a2b8
8 changed files with 93 additions and 25 deletions

View File

@ -1283,6 +1283,7 @@ hint.guardian = [accent]Guardian[] units are armored. Weak ammo such as [accent]
hint.coreUpgrade = Cores can be upgraded by [accent]placing higher-tier cores over them[].\n\nPlace a  [accent]Foundation[] core over the  [accent]Shard[] core. Make sure it is free from nearby obstructions.
hint.presetLaunch = Gray [accent]landing zone sectors[], such as [accent]Frozen Forest[], can be launched to from anywhere. They do not require capture of nearby territory.\n\n[accent]Numbered sectors[], such as this one, are [accent]optional[].
hint.coreIncinerate = After the core is filled to capacity with an item, any extra items of that type it receives will be [accent]incinerated[].
hint.coopCampaign = When playing the [accent]co-op campaign[], items that are produced in the current map will also be sent [accent]to your local sectors[].\n\nAny new research done by the host also carries over.
item.copper.description = Used in all types of construction and ammunition.
item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced.

View File

@ -153,6 +153,18 @@ public class Logic implements ApplicationListener{
}
});
//send out items to each client
Events.on(TurnEvent.class, e -> {
if(net.server() && state.isCampaign()){
int[] out = new int[content.items().size];
state.getSector().info.production.each((item, stat) -> {
out[item.id] = Math.max(0, (int)(stat.mean * turnDuration / 60));
});
Call.sectorProduced(out);
}
});
}
/** Adds starting items, resets wave time, and sets state to playing. */
@ -297,8 +309,46 @@ public class Logic implements ApplicationListener{
public static void researched(Content content){
if(!(content instanceof UnlockableContent u)) return;
var node = u.node();
//unlock all direct dependencies on client, permanently
while(node != null){
node.content.unlock();
node = node.parent;
}
state.rules.researched.add(u.name);
Events.fire(new UnlockEvent(u));
}
//called when the remote server runs a turn and produces something
@Remote
public static void sectorProduced(int[] amounts){
if(!state.isCampaign()) return;
Planet planet = state.rules.sector.planet;
boolean any = false;
for(Item item : content.items()){
int am = amounts[item.id];
if(am > 0){
int sumMissing = planet.sectors.sum(s -> s.hasBase() ? s.info.storageCapacity - s.info.items.get(item) : 0);
if(sumMissing == 0) continue;
//how much % to add
double percent = Math.min((double)am / sumMissing, 1);
for(Sector sec : planet.sectors){
if(sec.hasBase()){
int added = (int)Math.ceil(((sec.info.storageCapacity - sec.info.items.get(item)) * percent));
sec.info.items.add(item, added);
any = true;
}
}
}
}
if(any){
for(Sector sec : planet.sectors){
sec.saveInfo();
}
}
}
@Override

View File

@ -117,7 +117,7 @@ public abstract class UnlockableContent extends MappableContent{
/** Makes this piece of content unlocked; if it already unlocked, nothing happens. */
public void unlock(){
if(!net.client() && !unlocked()){
if(!unlocked && !alwaysUnlocked){
unlocked = true;
Core.settings.put(name + "-unlocked", true);
@ -135,7 +135,7 @@ public abstract class UnlockableContent extends MappableContent{
}
public boolean unlocked(){
if(net != null && net.client()) return alwaysUnlocked || state.rules.researched.contains(name);
if(net != null && net.client()) return unlocked || alwaysUnlocked || state.rules.researched.contains(name);
return unlocked || alwaysUnlocked;
}

View File

@ -547,6 +547,22 @@ public class TypeIO{
return read.b(new byte[length]);
}
public static void writeInts(Writes write, int[] ints){
write.s((short)ints.length);
for(int i : ints){
write.i(i);
}
}
public static int[] readInts(Reads read){
short length = read.s();
int[] out = new int[length];
for(int i = 0; i < length; i++){
out[i] = read.i();
}
return out;
}
public static void writeTraceInfo(Writes write, TraceInfo trace){
writeString(write, trace.ip);
writeString(write, trace.uuid);

View File

@ -173,6 +173,7 @@ public class HintsFragment extends Fragment{
&& SectorPresets.frozenForest.sector.save == null,
() -> state.isCampaign() && state.getSector().preset == SectorPresets.frozenForest),
coreIncinerate(() -> state.isCampaign() && state.rules.defaultTeam.core() != null && state.rules.defaultTeam.core().items.get(Items.copper) >= state.rules.defaultTeam.core().storageCapacity - 10, () -> false),
coopCampaign(() -> net.client() && state.isCampaign() && SectorPresets.groundZero.sector.hasBase(), () -> false),
;
@Nullable

View File

@ -6,6 +6,7 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
@ -246,17 +247,18 @@ public class CoreBlock extends StorageBlock{
}
state.teams.registerCore(this);
storageCapacity = itemCapacity + proximity().sum(e -> isContainer(e) && owns(e) ? e.block.itemCapacity : 0);
proximity.each(e -> isContainer(e) && owns(e), t -> {
storageCapacity = itemCapacity + proximity().sum(e -> owns(e) ? e.block.itemCapacity : 0);
proximity.each(e -> owns(e), t -> {
t.items = items;
((StorageBuild)t).linkedCore = this;
});
for(Building other : state.teams.cores(team)){
if(other.tile() == tile) continue;
storageCapacity += other.block.itemCapacity + other.proximity().sum(e -> isContainer(e) && owns(other, e) ? e.block.itemCapacity : 0);
storageCapacity += other.block.itemCapacity + other.proximity().sum(e -> owns(e) && owns(other, e) ? e.block.itemCapacity : 0);
}
//Team.sharded.core().items.set(Items.surgeAlloy, 12000)
if(!world.isGenerating()){
for(Item item : content.items()){
items.set(item, Math.min(items.get(item), storageCapacity));
@ -303,24 +305,19 @@ public class CoreBlock extends StorageBlock{
Draw.rect("block-select", t.x + offset * p.x, t.y + offset * p.y, i * 90);
}
};
if(proximity.contains(e -> isContainer(e) && e.items == items)){
if(proximity.contains(e -> owns(e) && e.items == items)){
outline.get(this);
}
proximity.each(e -> isContainer(e) && e.items == items, outline);
proximity.each(e -> owns(e) && e.items == items, outline);
Draw.reset();
}
public boolean isContainer(Building tile){
return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == this || ((StorageBuild)tile).linkedCore == null);
}
public boolean owns(Building tile){
return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == this || ((StorageBuild)tile).linkedCore == null);
return owns(this, tile);
}
public boolean owns(Building core, Building tile){
return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == core || ((StorageBuild)tile).linkedCore == null);
return tile instanceof StorageBuild b && (b.linkedCore == core || b.linkedCore == null);
}
public boolean incinerate(){
@ -340,7 +337,7 @@ public class CoreBlock extends StorageBlock{
int total = proximity.count(e -> e.items != null && e.items == items);
float fract = 1f / total / state.teams.cores(team).size;
proximity.each(e -> isContainer(e) && e.items == items && owns(e), t -> {
proximity.each(e -> owns(e) && e.items == items && owns(e), t -> {
StorageBuild ent = (StorageBuild)t;
ent.linkedCore = null;
ent.items = new ItemModule();

View File

@ -91,14 +91,16 @@ public class StorageBlock extends Block{
@Override
public void overwrote(Seq<Building> previous){
for(Building other : previous){
if(other.items != null){
items.add(other.items);
//only add prev items when core is not linked
if(linkedCore == null){
for(Building other : previous){
if(other.items != null && other.items != items){
items.add(other.items);
}
}
}
//ensure item counts are not too high
items.each((i, a) -> items.set(i, Math.min(a, itemCapacity)));
items.each((i, a) -> items.set(i, Math.min(a, itemCapacity)));
}
}
@Override

View File

@ -31,8 +31,8 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback,
final NetProvider provider;
final PacketSerializer serializer = new PacketSerializer();
final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(1024 * 4);
final ByteBuffer readBuffer = ByteBuffer.allocateDirect(1024 * 4);
final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(16384);
final ByteBuffer readBuffer = ByteBuffer.allocateDirect(16384);
final CopyOnWriteArrayList<SteamConnection> connections = new CopyOnWriteArrayList<>();
final IntMap<SteamConnection> steamConnections = new IntMap<>(); //maps steam ID -> valid net connection
@ -131,9 +131,10 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback,
writeBuffer.limit(writeBuffer.capacity());
writeBuffer.position(0);
serializer.write(writeBuffer, object);
int length = writeBuffer.position();
writeBuffer.flip();
snet.sendP2PPacket(currentServer, writeBuffer, mode == SendMode.tcp ? P2PSend.Reliable : P2PSend.UnreliableNoDelay, 0);
snet.sendP2PPacket(currentServer, writeBuffer, mode == SendMode.tcp || length >= 1200 ? P2PSend.Reliable : P2PSend.UnreliableNoDelay, 0);
}catch(Exception e){
net.showError(e);
}