public void DebugVeinMaps(ICoreServerAPI api, IMapRegion mapRegion, int regionX, int regionZ) { TyronThreadPool.QueueTask(() => { DirectoryInfo path = Directory.CreateDirectory(Path.Combine(GamePaths.DataPath, "VeinMaps", api.World.Seed.ToString())); Dictionary <string, IntDataMap2D> veinMaps = mapRegion.GetModdata <Dictionary <string, IntDataMap2D> >("veinmaps"); foreach (var vein in veinMaps) { IntDataMap2D veinMap = vein.Value; Bitmap bmp = new Bitmap(veinMap.Size, veinMap.Size); for (int x = 0; x < veinMap.Size; x++) { for (int y = 0; y < veinMap.Size; y++) { Argb8 test = new Argb8(veinMap.GetInt(x, y)); bmp.SetPixel(x, y, Color.FromArgb(test.Value)); } } Directory.CreateDirectory(Path.Combine(path.FullName, vein.Key.UcFirst())); string pt = Path.Combine(path.FullName, vein.Key.UcFirst(), string.Format("{0}, {1}.png", regionX, regionZ)); bmp.Save(pt, ImageFormat.Png); } }); }
/// <summary> /// Recomposes the element for lines. /// </summary> public void RecomposeText(bool async = false) { if (autoHeight) { AutoHeight(); } if (async) { TyronThreadPool.QueueTask(() => { ImageSurface surface = new ImageSurface(Format.Argb32, (int)Bounds.InnerWidth, (int)Bounds.InnerHeight); Context ctx = genContext(surface); DrawMultilineTextAt(ctx, 0, 0, orientation); api.Event.EnqueueMainThreadTask(() => { generateTexture(surface, ref textTexture); ctx.Dispose(); surface.Dispose(); }, "recompstatbar"); }); } else { ImageSurface surface = new ImageSurface(Format.Argb32, (int)Bounds.InnerWidth, (int)Bounds.InnerHeight); Context ctx = genContext(surface); DrawMultilineTextAt(ctx, 0, 0, orientation); generateTexture(surface, ref textTexture); ctx.Dispose(); surface.Dispose(); } }
// For some reason, this won't work as an extension method. private void PurgeWaypoints(System.Func <Waypoint, bool> comparer) { TyronThreadPool.QueueTask(() => { var wpLayer = _mapManager.WaypointMapLayer(); var waypoints = new List <int>(); for (var i = 0; i < wpLayer.ownWaypoints.Count; i++) { if (comparer(wpLayer.ownWaypoints[i])) { waypoints.Add(i); } } waypoints.Sort((a, b) => b.CompareTo(a)); foreach (var num in waypoints) { Api.Event.EnqueueMainThreadTask(() => Api.SendChatMessage($"/waypoint remove {num}"), ""); } Api.Event.EnqueueMainThreadTask(() => Api.Event.RegisterCallback(dt => _mapManager.GetField <IClientNetworkChannel>("clientChannel") .SendPacket(new OnViewChangedPacket()), 500), ""); }); }
void PrepareForLoading(int threadsCount) { // JSON parsing is slooowww, so let's multithread the **** out of it :) for (int i = 0; i < threadsCount; i++) { TyronThreadPool.QueueTask(GatherAllTypes_Async); } }
void recomposeOverlays() { TyronThreadPool.QueueTask(() => { ComposeValueOverlay(); ComposeFlashOverlay(); }); if (ShowValueOnHover) { api.Gui.TextTexture.GenOrUpdateTextTexture(onGetStatbarValue(), valueFont, ref valueTexture, new TextBackground() { FillColor = GuiStyle.DialogStrongBgColor, Padding = 5, BorderWidth = 2 }); } }
public override void AssetsLoaded(ICoreAPI coreApi) { if (!(coreApi is ICoreServerAPI api)) { return; } this.api = api; api.Logger.VerboseDebug("Starting to gather blocktypes, itemtypes and entities"); LoadWorldProperties(); int threads = Math.Max(1, Environment.ProcessorCount / 2 - 2); itemTypes = new Dictionary <AssetLocation, RegistryObjectType>(); blockTypes = new Dictionary <AssetLocation, RegistryObjectType>(); entityTypes = new Dictionary <AssetLocation, RegistryObjectType>(); foreach (KeyValuePair <AssetLocation, JObject> entry in api.Assets.GetMany <JObject>(api.Server.Logger, "itemtypes/")) { try { ItemType et = new ItemType(); et.CreateBasetype(entry.Key.Domain, entry.Value); itemTypes.Add(entry.Key, et); } catch (Exception e) { api.World.Logger.Error("Item type {0} could not be loaded. Will ignore. Exception thrown: {1}", entry.Key, e); continue; } } itemVariants = new List <RegistryObjectType> [itemTypes.Count]; api.Logger.VerboseDebug("Starting parsing ItemTypes in " + threads + " threads"); PrepareForLoading(threads); foreach (KeyValuePair <AssetLocation, JObject> entry in api.Assets.GetMany <JObject>(api.Server.Logger, "entities/")) { try { EntityType et = new EntityType(); et.CreateBasetype(entry.Key.Domain, entry.Value); entityTypes.Add(entry.Key, et); } catch (Exception e) { api.World.Logger.Error("Entity type {0} could not be loaded. Will ignore. Exception thrown: {1}", entry.Key, e); continue; } } entityVariants = new List <RegistryObjectType> [entityTypes.Count]; foreach (KeyValuePair <AssetLocation, JObject> entry in api.Assets.GetMany <JObject>(api.Server.Logger, "blocktypes/")) { try { BlockType et = new BlockType(); et.CreateBasetype(entry.Key.Domain, entry.Value); blockTypes.Add(entry.Key, et); } catch (Exception e) { api.World.Logger.Error("Block type {0} could not be loaded. Will ignore. Exception thrown: {1}", entry.Key, e); continue; } } blockVariants = new List <RegistryObjectType> [blockTypes.Count]; TyronThreadPool.QueueTask(GatherAllTypes_Async); // Now we've loaded everything, let's add one more gathering thread :) api.Logger.StoryEvent(Lang.Get("It remembers...")); api.Logger.VerboseDebug("Gathered all types, starting to load items"); LoadItems(itemVariants); api.Logger.VerboseDebug("Parsed and loaded items"); api.Logger.StoryEvent(Lang.Get("...all that came before")); LoadBlocks(blockVariants); api.Logger.VerboseDebug("Parsed and loaded blocks"); LoadEntities(entityVariants); api.Logger.VerboseDebug("Parsed and loaded entities"); api.Server.LogNotification("BlockLoader: Entities, Blocks and Items loaded"); FreeRam(); api.TriggerOnAssetsFirstLoaded(); }
public virtual void TesselateShape() { if (!loaded) { return; } shapeFresh = true; CompositeShape compositeShape = OverrideCompositeShape != null ? OverrideCompositeShape : entity.Properties.Client.Shape; Shape entityShape = OverrideEntityShape != null ? OverrideEntityShape : entity.Properties.Client.LoadedShapeForEntity; if (entityShape == null) { return; } OnTesselation?.Invoke(ref entityShape, compositeShape.Base.ToString()); entity.OnTesselation(ref entityShape, compositeShape.Base.ToString()); defaultTexSource = GetTextureSource(); TyronThreadPool.QueueTask(() => { MeshData meshdata; if (entity.Properties.Client.Shape.VoxelizeTexture) { int altTexNumber = entity.WatchedAttributes.GetInt("textureIndex", 0); TextureAtlasPosition pos = defaultTexSource["all"]; CompositeTexture[] Alternates = entity.Properties.Client.FirstTexture.Alternates; CompositeTexture tex = altTexNumber == 0 ? entity.Properties.Client.FirstTexture : Alternates[altTexNumber % Alternates.Length]; meshdata = capi.Tesselator.VoxelizeTexture(tex, capi.EntityTextureAtlas.Size, pos); for (int i = 0; i < meshdata.xyz.Length; i += 3) { meshdata.xyz[i] -= 0.125f; meshdata.xyz[i + 1] -= 0.5f; meshdata.xyz[i + 2] += 0.125f / 2; } } else { try { TesselationMetaData meta = new TesselationMetaData() { quantityElements = compositeShape.QuantityElements, selectiveElements = compositeShape.SelectiveElements, texSource = this, withJointIds = true, withDamageEffect = true, typeForLogging = "entity" }; capi.Tesselator.TesselateShape(meta, entityShape, out meshdata, new Vec3f(compositeShape.rotateX, compositeShape.rotateY, compositeShape.rotateZ)); meshdata.Translate(compositeShape.offsetX, compositeShape.offsetY, compositeShape.offsetZ); } catch (Exception e) { capi.World.Logger.Fatal("Failed tesselating entity {0} with id {1}. Entity will probably be invisible!. The teselator threw {2}", entity.Code, entity.EntityId, e); return; } } MeshData opaqueMesh = meshdata.Clone().Clear(); MeshData oitMesh = meshdata.Clone().Clear(); opaqueMesh.AddMeshData(meshdata, EnumChunkRenderPass.Opaque); oitMesh.AddMeshData(meshdata, EnumChunkRenderPass.Transparent); capi.Event.EnqueueMainThreadTask(() => { if (meshRefOpaque != null) { meshRefOpaque.Dispose(); meshRefOpaque = null; } if (meshRefOit != null) { meshRefOit.Dispose(); meshRefOit = null; } if (capi.IsShuttingDown) { return; } if (opaqueMesh.VerticesCount > 0) { meshRefOpaque = capi.Render.UploadMesh(opaqueMesh); } if (oitMesh.VerticesCount > 0) { meshRefOit = capi.Render.UploadMesh(oitMesh); } }, "uploadentitymesh"); capi.TesselatorManager.ThreadDispose(); }); }
void Recompose() { if (curSlot?.Itemstack == null) { return; } readyToRender = false; string title = curSlot.GetStackName(); string desc = OnRequireInfoText(curSlot); desc.TrimEnd(); titleElement.SetNewText(title, titleFont); descriptionElement.SetNewText(desc, Font); RecalcBounds(title, desc); Bounds.CalcWorldBounds(); ElementBounds textBounds = Bounds.CopyOnlySize(); textBounds.CalcWorldBounds(); TyronThreadPool.QueueTask(() => { /*int i = 0; * while (i < 5 && titleElement.HalfComposed) System.Threading.Thread.Sleep(5);*/ ImageSurface surface = new ImageSurface(Format.Argb32, Bounds.OuterWidthInt, Bounds.OuterHeightInt); Context ctx = genContext(surface); ctx.SetSourceRGBA(0, 0, 0, 0); ctx.Paint(); ctx.SetSourceRGBA(backTint[0], backTint[1], backTint[2], backTint[3]); RoundRectangle(ctx, textBounds.bgDrawX, textBounds.bgDrawY, textBounds.OuterWidthInt, textBounds.OuterHeightInt, GuiStyle.DialogBGRadius); ctx.FillPreserve(); ctx.SetSourceRGBA(GuiStyle.DialogLightBgColor[0] * 1.4, GuiStyle.DialogStrongBgColor[1] * 1.4, GuiStyle.DialogStrongBgColor[2] * 1.4, 1); ctx.LineWidth = 3 * 1.75; ctx.StrokePreserve(); surface.Blur(8.2); ctx.SetSourceRGBA(backTint[0] / 2, backTint[1] / 2, backTint[2] / 2, backTint[3]); ctx.Stroke(); int w = (int)(scaled(ItemStackSize) + scaled(40)); int h = (int)(scaled(ItemStackSize) + scaled(40)); ImageSurface shSurface = new ImageSurface(Format.Argb32, w, h); Context shCtx = genContext(shSurface); shCtx.SetSourceRGBA(GuiStyle.DialogSlotBackColor); RoundRectangle(shCtx, 0, 0, w, h, 0); shCtx.FillPreserve(); shCtx.SetSourceRGBA(GuiStyle.DialogSlotFrontColor); shCtx.LineWidth = 5; shCtx.Stroke(); shSurface.Blur(7); shSurface.Blur(7); shSurface.Blur(7); EmbossRoundRectangleElement(shCtx, 0, 0, w, h, true); ctx.SetSourceSurface(shSurface, (int)(textBounds.drawX), (int)(textBounds.drawY + scaled(MarginTop))); ctx.Rectangle(textBounds.drawX, textBounds.drawY + scaled(MarginTop), w, h); ctx.Fill(); shCtx.Dispose(); shSurface.Dispose(); api.Event.EnqueueMainThreadTask(() => { //titleElement.genTexture(); //descriptionElement.genTexture(); titleElement.Compose(false); descriptionElement.Compose(false); generateTexture(surface, ref texture); ctx.Dispose(); surface.Dispose(); double offset = (int)(30 + ItemStackSize / 2); scissorBounds = ElementBounds.Fixed(4 + offset - ItemStackSize, 2 + offset + MarginTop - ItemStackSize, ItemStackSize + 38, ItemStackSize + 38).WithParent(Bounds); scissorBounds.CalcWorldBounds(); readyToRender = true; }, "genstackinfotexture"); }); }
private void updateSounds(float dt) { float targetRainVolumeLeafy = 0; float targetRainVolumeLeafless = 0; float targetHailVolume = 0; float targetTrembleVolume = 0; float targetRainPitch = 1; float targetHailPitch = 1; WeatherDataSnapshot weatherData = weatherSys.BlendedWeatherData; if (searchComplete) { EntityPlayer eplr = capi.World.Player.Entity; plrPos.Set((int)eplr.Pos.X, (int)eplr.Pos.Y, (int)eplr.Pos.Z); searchComplete = false; TyronThreadPool.QueueTask(() => { float val = (float)Math.Pow(Math.Max(0, (capi.World.BlockAccessor.GetDistanceToRainFall(plrPos, 12, 4) - 2) / 10f), 2); roomVolumePitchLoss = GameMath.Clamp(val, 0, 1); searchComplete = true; }); } EnumPrecipitationType precType = weatherData.BlendedPrecType; if (precType == EnumPrecipitationType.Auto) { precType = weatherSys.clientClimateCond?.Temperature < weatherData.snowThresholdTemp ? EnumPrecipitationType.Snow : EnumPrecipitationType.Rain; } float nearbyLeaviness = GameMath.Clamp(GlobalConstants.CurrentNearbyRelLeavesCountClient * 60, 0, 1); ClimateCondition conds = weatherSys.clientClimateCond; if (conds.Rainfall > 0) { if (precType == EnumPrecipitationType.Rain || weatherSys.clientClimateCond.Temperature < weatherData.snowThresholdTemp) { targetRainVolumeLeafy = nearbyLeaviness * GameMath.Clamp(conds.Rainfall * 2f - Math.Max(0, 2f * (weatherData.snowThresholdTemp - weatherSys.clientClimateCond.Temperature)), 0, 1); targetRainVolumeLeafy = GameMath.Max(0, targetRainVolumeLeafy - roomVolumePitchLoss); targetRainVolumeLeafless = Math.Max(0.3f, 1 - nearbyLeaviness) * GameMath.Clamp(conds.Rainfall * 2f - Math.Max(0, 2f * (weatherData.snowThresholdTemp - weatherSys.clientClimateCond.Temperature)), 0, 1); targetRainVolumeLeafless = GameMath.Max(0, targetRainVolumeLeafless - roomVolumePitchLoss); targetRainPitch = Math.Max(0.7f, 1.25f - conds.Rainfall * 0.7f); targetRainPitch = Math.Max(0, targetRainPitch - roomVolumePitchLoss / 4f); targetTrembleVolume = GameMath.Clamp(conds.Rainfall * 1.6f - 0.8f - roomVolumePitchLoss * 0.25f, 0, 1); if (!rainSoundsOn && (targetRainVolumeLeafy > 0.01 || targetRainVolumeLeafless > 0.01)) { for (int i = 0; i < rainSoundsLeafless.Length; i++) { rainSoundsLeafless[i]?.Start(); } for (int i = 0; i < rainSoundsLeafy.Length; i++) { rainSoundsLeafy[i]?.Start(); } lowTrembleSound?.Start(); rainSoundsOn = true; curRainPitch = targetRainPitch; } if (capi.World.Player.Entity.IsEyesSubmerged()) { curRainPitch = targetRainPitch / 2; targetRainVolumeLeafy *= 0.75f; targetRainVolumeLeafless *= 0.75f; } } if (precType == EnumPrecipitationType.Hail) { targetHailVolume = GameMath.Clamp(conds.Rainfall * 2f - roomVolumePitchLoss, 0, 1); targetHailVolume = GameMath.Max(0, targetHailVolume - roomVolumePitchLoss); targetHailPitch = Math.Max(0.7f, 1.25f - conds.Rainfall * 0.7f); targetHailPitch = Math.Max(0, targetHailPitch - roomVolumePitchLoss / 4f); if (!hailSoundsOn && targetHailVolume > 0.01) { hailSound?.Start(); hailSoundsOn = true; curHailPitch = targetHailPitch; } } } curRainVolumeLeafy += (targetRainVolumeLeafy - curRainVolumeLeafy) * dt / 2; curRainVolumeLeafless += (targetRainVolumeLeafless - curRainVolumeLeafless) * dt / 2; curTrembleVolume += (targetTrembleVolume - curTrembleVolume) * dt; curHailVolume += (targetHailVolume - curHailVolume) * dt; curHailPitch += (targetHailPitch - curHailPitch) * dt; curRainPitch += (targetRainPitch - curRainPitch) * dt; if (rainSoundsOn) { for (int i = 0; i < rainSoundsLeafless.Length; i++) { rainSoundsLeafless[i]?.SetVolume(curRainVolumeLeafless); rainSoundsLeafless[i]?.SetPitch(curRainPitch); } for (int i = 0; i < rainSoundsLeafy.Length; i++) { rainSoundsLeafy[i]?.SetVolume(curRainVolumeLeafy); rainSoundsLeafy[i]?.SetPitch(curRainPitch); } lowTrembleSound?.SetVolume(curTrembleVolume); } if (hailSoundsOn) { hailSound?.SetVolume(curHailVolume); hailSound?.SetPitch(curHailPitch); } if (curRainVolumeLeafless < 0.01 && curRainVolumeLeafy < 0.01) { for (int i = 0; i < rainSoundsLeafless.Length; i++) { rainSoundsLeafless[i]?.Stop(); } for (int i = 0; i < rainSoundsLeafy.Length; i++) { rainSoundsLeafy[i]?.Stop(); } rainSoundsOn = false; } if (curHailVolume < 0.01) { hailSound?.Stop(); hailSoundsOn = false; } float wstr = (1 - roomVolumePitchLoss) * weatherData.curWindSpeed.X - 0.3f; if (wstr > 0.03f || curWindVolumeLeafy > 0.01f || curWindVolumeLeafless > 0.01f) { if (!windSoundsOn) { windSoundLeafy?.Start(); windSoundLeafless?.Start(); windSoundsOn = true; } float targetVolumeLeafy = nearbyLeaviness * 1.2f * wstr; float targetVolumeLeafless = (1 - nearbyLeaviness) * 1.2f * wstr; curWindVolumeLeafy += (targetVolumeLeafy - curWindVolumeLeafy) * dt; curWindVolumeLeafless += (targetVolumeLeafless - curWindVolumeLeafless) * dt; windSoundLeafy?.SetVolume(curWindVolumeLeafy); windSoundLeafless?.SetVolume(curWindVolumeLeafless); } else { if (windSoundsOn) { windSoundLeafy?.Stop(); windSoundLeafless?.Stop(); windSoundsOn = false; } } }