private void Update() { gameStateUpdateTimer += Time.deltaTime; gameResearchHashUpdateTimer += Time.deltaTime; productionStatisticsUpdateTimer += Time.deltaTime; if (gameStateUpdateTimer > GAME_STATE_UPDATE_INTERVAL) { gameStateUpdateTimer = 0; SendPacket(new GameStateUpdate() { State = new GameState(TimeUtils.CurrentUnixTimestampMilliseconds(), GameMain.gameTick) }); } if (gameResearchHashUpdateTimer > GAME_RESEARCH_UPDATE_INTERVAL) { gameResearchHashUpdateTimer = 0; if (GameMain.data.history.currentTech != 0) { TechState state = GameMain.data.history.techStates[GameMain.data.history.currentTech]; SendPacket(new GameHistoryResearchUpdatePacket(GameMain.data.history.currentTech, state.hashUploaded)); } } if (productionStatisticsUpdateTimer > STATISTICS_UPDATE_INTERVAL) { productionStatisticsUpdateTimer = 0; StatisticsManager.SendBroadcastIfNeeded(); } PacketProcessor.ProcessPacketQueue(); }
void Initializing() { TechTreeList = new List <TechState>(); FacilityList = new List <TechRecipe.FacilityInfo>(); ActorList = new List <TechRecipe.ProcessActorInfo>(); ResearchStateList = new List <ResearchState>(); TechState newState; foreach (var Info in TechRecipeCall.TechInfoList) { newState = new TechState(); newState.Info = Info; newState.Completed = false; newState.Possible = false; TechTreeList.Add(newState); } ResearchState FirstResearch = new ResearchState(); FirstResearch.LabatoryList = new List <GameObject>(); FirstResearch.TargetState = TechTreeList[0]; ResearchStateList.Add(FirstResearch); CompleteResearch(FirstResearch); CheckTechPossible(); }
public override void ProcessPacket(GameHistoryUnlockTechPacket packet, NebulaConnection conn) { Log.Info($"Unlocking tech (ID: {packet.TechId})"); using (Multiplayer.Session.History.IsIncomingRequest.On()) { // Let the default method give back the items GameMain.mainPlayer.mecha.lab.ManageTakeback(); // Update techState TechProto techProto = LDB.techs.Select(packet.TechId); TechState techState = GameMain.history.techStates[packet.TechId]; if (techState.curLevel >= techState.maxLevel) { techState.curLevel = techState.maxLevel; techState.hashUploaded = techState.hashNeeded; techState.unlocked = true; } else { techState.curLevel++; techState.hashUploaded = 0L; techState.hashNeeded = techProto.GetHashNeeded(techState.curLevel); } // UnlockTech() unlocks tech to techState.maxLevel, so change it to curLevel temporarily int maxLevl = techState.maxLevel; techState.maxLevel = techState.curLevel; GameMain.history.techStates[packet.TechId] = techState; GameMain.history.UnlockTech(packet.TechId); techState.maxLevel = maxLevl; GameMain.history.techStates[packet.TechId] = techState; GameMain.history.DequeueTech(); } }
public void ProcessPacket(GameHistoryResearchUpdatePacket packet, NebulaConnection conn) { GameHistoryData data = GameMain.data.history; if (packet.TechId != data.currentTech) { //Wait for the authoritative packet to enqueu new tech first return; } TechState state = data.techStates[data.currentTech]; state.hashUploaded = packet.HashUploaded; data.techStates[data.currentTech] = state; }
public override void Update() { PacketProcessor.ProcessPacketQueue(); if (Multiplayer.Session.IsGameLoaded) { gameResearchHashUpdateTimer += Time.deltaTime; productionStatisticsUpdateTimer += Time.deltaTime; dysonLaunchUpateTimer += Time.deltaTime; dysonSphereUpdateTimer += Time.deltaTime; warningUpdateTimer += Time.deltaTime; if (gameResearchHashUpdateTimer > GAME_RESEARCH_UPDATE_INTERVAL) { gameResearchHashUpdateTimer = 0; if (GameMain.data.history.currentTech != 0) { TechState state = GameMain.data.history.techStates[GameMain.data.history.currentTech]; SendPacket(new GameHistoryResearchUpdatePacket(GameMain.data.history.currentTech, state.hashUploaded, state.hashNeeded)); } } if (productionStatisticsUpdateTimer > STATISTICS_UPDATE_INTERVAL) { productionStatisticsUpdateTimer = 0; Multiplayer.Session.Statistics.SendBroadcastIfNeeded(); } if (dysonLaunchUpateTimer > LAUNCH_UPDATE_INTERVAL) { dysonLaunchUpateTimer = 0; Multiplayer.Session.Launch.SendBroadcastIfNeeded(); } if (dysonSphereUpdateTimer > DYSONSPHERE_UPDATE_INTERVAL) { dysonSphereUpdateTimer = 0; Multiplayer.Session.DysonSpheres.UpdateSphereStatusIfNeeded(); } if (warningUpdateTimer > WARNING_UPDATE_INTERVAL) { warningUpdateTimer = 0; Multiplayer.Session.Warning.SendBroadcastIfNeeded(); } } }
public override void ProcessPacket(GameHistoryResearchUpdatePacket packet, NebulaConnection conn) { GameHistoryData data = GameMain.data.history; if (packet.TechId != data.currentTech) { NebulaModel.Logger.Log.Warn($"CurrentTech mismatch! Server:{packet.TechId} Local:{data.currentTech}"); //Replace currentTech to match with server data.currentTech = packet.TechId; data.techQueue[0] = packet.TechId; } TechState state = data.techStates[data.currentTech]; state.hashUploaded = packet.HashUploaded; state.hashNeeded = packet.HashNeeded; data.techStates[data.currentTech] = state; }
private static void UnlockTechRecursive(int techId, GameHistoryData history) { TechState state = history.TechState(techId); TechProto proto = LDB.techs.Select(techId); foreach (var techReq in proto.PreTechs) { if (!history.TechState(techReq).unlocked) { UnlockTechRecursive(techReq, history); } } foreach (var techReq in proto.PreTechsImplicit) { if (!history.TechState(techReq).unlocked) { UnlockTechRecursive(techReq, history); } } foreach (var itemReq in proto.itemArray) { if (itemReq.preTech is not null && !history.TechState(itemReq.preTech.ID).unlocked) { UnlockTechRecursive(itemReq.preTech.ID, history); } } int current = state.curLevel; for (; current < state.maxLevel; current++) { for (int j = 0; j < proto.UnlockFunctions.Length; j++) { history.UnlockTechFunction(proto.UnlockFunctions[j], proto.UnlockValues[j], current); } } history.UnlockTech(techId); }
public static void ParallelizeFactoryGameTick(ILContext il) { ILCursor c = new ILCursor(il); int forIndex = 3; var factoriesFld = typeof(GameData).GetField(nameof(GameData.factories), BindingFlags.Public | BindingFlags.Instance); Func <Instruction, bool>[] searchArray = new Func <Instruction, bool>[] { x => x.MatchLdcI4(0), x => x.MatchStloc(out forIndex), x => x.MatchBr(out _), x => x.MatchLdarg(0), x => x.MatchLdfld(factoriesFld), x => x.MatchLdloc(forIndex), x => x.MatchLdelemRef(), x => x.MatchBrfalse(out _), x => x.MatchLdarg(0), x => x.MatchLdfld(factoriesFld), x => x.MatchLdloc(forIndex), x => x.MatchLdelemRef(), x => x.MatchLdarg(1), x => x.MatchCallOrCallvirt(typeof(PlanetFactory).GetMethod(nameof(PlanetFactory.GameTick), BindingFlags.Public | BindingFlags.Instance)), x => x.MatchLdloc(forIndex), x => x.MatchLdcI4(1), x => x.MatchAdd(), x => x.MatchStloc(forIndex), x => x.MatchLdloc(forIndex), x => x.MatchLdarg(0), x => x.MatchLdfld(typeof(GameData).GetField(nameof(GameData.factoryCount), BindingFlags.Public | BindingFlags.Instance)), x => x.MatchBlt(out _) }; c.GotoNext(MoveType.Before, searchArray); var retLabel = c.MarkLabel(); c.Index -= 1; c.Emit(OpCodes.Ldarg_0); c.Emit(OpCodes.Ldarg_1); c.EmitDelegate <Func <GameData, long, bool> >((data, time) => { bool flag = false; int currentTech = data.history.currentTech; TechProto techProto = LDB.techs.Select(currentTech); TechState techState = default(TechState); if (currentTech > 0 && techProto != null && techProto.IsLabTech && GameMain.history.techStates.ContainsKey(currentTech)) { techState = data.history.techStates[currentTech]; flag = true; } if (flag && Math.Abs(techState.hashUploaded - techState.hashNeeded) < 7200L) { return(true); } else { Parallel.ForEach(data.factories, (factory) => { if (factory is not null) { factory.GameTick(time); } }); return(false); } }); c.Index += searchArray.Length; var branchLabel = c.MarkLabel(); c.GotoLabel(retLabel, MoveType.Before); c.Emit(OpCodes.Brfalse, branchLabel); }
public static void AddPlanetFactoryData(PlanetFactory planetFactory) { var factorySystem = planetFactory.factorySystem; var transport = planetFactory.transport; var veinPool = planetFactory.planet.factory.veinPool; var miningSpeedScale = (double)GameMain.history.miningSpeedScale; for (int i = 1; i < factorySystem.minerCursor; i++) { var miner = factorySystem.minerPool[i]; if (i != miner.id) { continue; } var productId = miner.productId; var veinId = (miner.veinCount != 0) ? miner.veins[miner.currentVeinIndex] : 0; if (miner.type == EMinerType.Water) { productId = planetFactory.planet.waterItemId; } else if (productId == 0) { productId = veinPool[veinId].productId; } if (productId == 0) { continue; } EnsureId(ref counter, productId); float frequency = 60f / (float)((double)miner.period / 600000.0); float speed = (float)(0.0001 * (double)miner.speed * miningSpeedScale); float production = 0f; if (factorySystem.minerPool[i].type == EMinerType.Water) { production = frequency * speed; } if (factorySystem.minerPool[i].type == EMinerType.Oil) { production = frequency * speed * (float)((double)veinPool[veinId].amount * (double)VeinData.oilSpeedMultiplier); } if (factorySystem.minerPool[i].type == EMinerType.Vein) { production = frequency * speed * miner.veinCount; } production = Math.Min(BELT_MAX_ITEMS_PER_MINUTE, production); counter[productId].production += production; counter[productId].producers++; } for (int i = 1; i < factorySystem.assemblerCursor; i++) { var assembler = factorySystem.assemblerPool[i]; if (assembler.id != i || assembler.recipeId == 0) { continue; } var frequency = 60f / (float)((double)assembler.timeSpend / 600000.0); var speed = (float)(0.0001 * (double)assembler.speed); for (int j = 0; j < assembler.requires.Length; j++) { var productId = assembler.requires[j]; EnsureId(ref counter, productId); counter[productId].consumption += frequency * speed * assembler.requireCounts[j]; counter[productId].consumers++; } for (int j = 0; j < assembler.products.Length; j++) { var productId = assembler.products[j]; EnsureId(ref counter, productId); counter[productId].production += frequency * speed * assembler.productCounts[j]; counter[productId].producers++; } } for (int i = 1; i < factorySystem.fractionateCursor; i++) { var fractionator = factorySystem.fractionatePool[i]; if (fractionator.id != i) { continue; } if (fractionator.fluidId != 0) { var productId = fractionator.fluidId; EnsureId(ref counter, productId); counter[productId].consumption += 60f * 30f * fractionator.produceProb; counter[productId].consumers++; } if (fractionator.productId != 0) { var productId = fractionator.productId; EnsureId(ref counter, productId); counter[productId].production += 60f * 30f * fractionator.produceProb; counter[productId].producers++; } } for (int i = 1; i < factorySystem.ejectorCursor; i++) { var ejector = factorySystem.ejectorPool[i]; if (ejector.id != i) { continue; } EnsureId(ref counter, ejector.bulletId); counter[ejector.bulletId].consumption += 60f / (float)(ejector.chargeSpend + ejector.coldSpend) * 600000f; counter[ejector.bulletId].consumers++; } for (int i = 1; i < factorySystem.siloCursor; i++) { var silo = factorySystem.siloPool[i]; if (silo.id != i) { continue; } EnsureId(ref counter, silo.bulletId); counter[silo.bulletId].consumption += 60f / (float)(silo.chargeSpend + silo.coldSpend) * 600000f; counter[silo.bulletId].consumers++; } for (int i = 1; i < factorySystem.labCursor; i++) { var lab = factorySystem.labPool[i]; if (lab.id != i) { continue; } float frequency = 60f / (float)((double)lab.timeSpend / 600000.0); if (lab.matrixMode) { for (int j = 0; j < lab.requires.Length; j++) { var productId = lab.requires[j]; EnsureId(ref counter, productId); counter[productId].consumption += frequency * lab.requireCounts[j]; counter[productId].consumers++; } for (int j = 0; j < lab.products.Length; j++) { var productId = lab.products[j]; EnsureId(ref counter, productId); counter[productId].production += frequency * lab.productCounts[j]; counter[productId].producers++; } } else if (lab.researchMode && lab.techId > 0) { // In this mode we can't just use lab.timeSpend to figure out how long it takes to consume 1 item (usually a cube) // So, we figure out how many hashes a single cube represents and use the research mode research speed to come up with what is basically a research rate var techProto = LDB.techs.Select(lab.techId); if (techProto == null) { continue; } TechState techState = GameMain.history.TechState(techProto.ID); for (int index = 0; index < techProto.itemArray.Length; ++index) { var item = techProto.Items[index]; var cubesNeeded = techProto.GetHashNeeded(techState.curLevel) * techProto.ItemPoints[index] / 3600L; var researchRate = GameMain.history.techSpeed * 60.0f; var hashesPerCube = (float)techState.hashNeeded / cubesNeeded; var researchFreq = hashesPerCube / researchRate; EnsureId(ref counter, item); counter[item].consumers++; counter[item].consumption += researchFreq * GameMain.history.techSpeed; } } } double gasTotalHeat = planetFactory.planet.gasTotalHeat; var collectorsWorkCost = transport.collectorsWorkCost; for (int i = 1; i < transport.stationCursor; i++) { var station = transport.stationPool[i]; if (station == null || station.id != i || !station.isCollector) { continue; } float collectSpeedRate = (gasTotalHeat - collectorsWorkCost > 0.0) ? ((float)((miningSpeedScale * gasTotalHeat - collectorsWorkCost) / (gasTotalHeat - collectorsWorkCost))) : 1f; for (int j = 0; j < station.collectionIds.Length; j++) { var productId = station.collectionIds[j]; EnsureId(ref counter, productId); counter[productId].production += 60f * TICKS_PER_SEC * station.collectionPerTick[j] * collectSpeedRate; counter[productId].producers++; } } for (int i = 1; i < planetFactory.powerSystem.genCursor; i++) { var generator = planetFactory.powerSystem.genPool[i]; if (generator.id != i) { continue; } var isFuelConsumer = generator.fuelHeat > 0 && generator.fuelId > 0 && generator.productId == 0; if ((generator.productId == 0 || generator.productHeat == 0) && !isFuelConsumer) { continue; } if (isFuelConsumer) { // account for fuel consumption by power generator var productId = generator.fuelId; EnsureId(ref counter, productId); counter[productId].consumption += 60.0f * TICKS_PER_SEC * generator.useFuelPerTick / generator.fuelHeat; counter[productId].consumers++; } else { var productId = generator.productId; EnsureId(ref counter, productId); counter[productId].production += 60.0f * TICKS_PER_SEC * generator.capacityCurrentTick / generator.productHeat; counter[productId].producers++; if (generator.catalystId > 0) { // account for consumption of critical photons by ray receivers EnsureId(ref counter, generator.catalystId); counter[generator.catalystId].consumption += RAY_RECEIVER_GRAVITON_LENS_CONSUMPTION_RATE_PER_MIN; counter[generator.catalystId].consumers++; } } } }