public void ToolPaintBlock(IMyCubeGrid grid, Vector3I gridPosition, PaintMaterial paint, bool useMirroring) { if (paint.Skin.HasValue) { // vanilla DLC-locked skins should use API, mod-added should use the packet to force skin change. SkinInfo skin = Main.Palette.GetSkinInfo(paint.Skin.Value); if (!skin.AlwaysOwned) { if (useMirroring && (grid.XSymmetryPlane.HasValue || grid.YSymmetryPlane.HasValue || grid.ZSymmetryPlane.HasValue)) { MirrorData mirrorData = new MirrorData(grid); PaintBlockSymmetry(true, grid, gridPosition, paint, mirrorData, MyAPIGateway.Multiplayer.MyId); // no ammo consumption, it's creative usage anyway } else { PaintBlock(true, grid, gridPosition, paint, MyAPIGateway.Multiplayer.MyId); Main.NetworkLibHandler.PacketConsumeAmmo.Send(); } return; } } // for mod-added skins: Main.NetworkLibHandler.PacketPaint.Send(grid, gridPosition, paint, useMirroring); }
/// <summary> /// <param name="sync"></param> arg determines if it sends the paint request using the API, and automatically checks skin ownership. Must be false for mod-added skins. /// </summary> public void PaintBlock(bool sync, IMyCubeGrid grid, Vector3I gridPosition, PaintMaterial paint, ulong originalSenderSteamId) { IMySlimBlock slim = grid.GetCubeBlock(gridPosition); if (sync) { grid.SkinBlocks(gridPosition, gridPosition, paint.ColorMask, paint.Skin?.String); if (paint.Skin.HasValue) { // check if skin was applied to alert player CheckSkinned[slim] = new CheckData(paint.Skin.Value); // add or replace SetUpdateMethods(UpdateFlags.UPDATE_AFTER_SIM, true); } } else { // NOTE getting a MySlimBlock and sending it straight to arguments avoids getting prohibited errors. MyCubeGrid gridInternal = (MyCubeGrid)grid; gridInternal.ChangeColorAndSkin(gridInternal.GetCubeBlock(gridPosition), paint.ColorMask, paint.Skin); if (paint.Skin.HasValue) { CheckSkinned.Remove(slim); // prevent alerting if skin gets changed into an always-owned one } } }
public SerializedPaintMaterial(PaintMaterial material) { ColorMaskPacked = null; if (material.ColorMask.HasValue) { ColorMaskPacked = material.ColorMask.Value.PackHSVToUint(); } Skin = material.Skin; }
/// <summary> /// Gets color and skin from supplied paint material which can be from blocks or players' palette. /// If color doesn't exist in palette it will replace currently selected slot, otherwise it selects the existing color slot. /// Respects nullability from PaintMaterial (applycolor/skin toggles from other players). /// </summary> public void GrabPaletteFromPaint(PaintMaterial pickedMaterial, bool changeApply = false) { if (SetColorAndSkin(pickedMaterial, changeApply)) { Main.HUDSounds.PlayMouseClick(); } else { Main.HUDSounds.PlayUnable(); } }
public void ToolReplacePaint(IMyCubeGrid grid, BlockMaterial oldPaint, PaintMaterial paint, bool includeSubgrids) { if (paint.Skin.HasValue) { // vanilla DLC-locked skins should use API, mod-added should use the packet to force skin change. SkinInfo skin = Main.Palette.GetSkinInfo(paint.Skin.Value); if (!skin.AlwaysOwned) { ReplaceColorInGrid(true, grid, oldPaint, paint, includeSubgrids, MyAPIGateway.Multiplayer.MyId); return; } } // for mod-added skins: Main.NetworkLibHandler.PacketReplacePaint.Send(grid, oldPaint, paint, includeSubgrids); }
void HandleInputs_InstantColorPick() { if (InputHandler.GetPressedOr(Main.Settings.instantColorPick1, Main.Settings.instantColorPick2)) { if (!colorPickInputPressed) { colorPickInputPressed = true; PreventIronSight(); if (Main.LocalToolHandler.AimedBlock != null || Main.LocalToolHandler.AimedBlock != null) { if (LocalInfo.ColorPickMode) { Main.Palette.ColorPickMode = false; } PaintMaterial paint; if (Main.LocalToolHandler.AimedBlock != null) { paint = new PaintMaterial(Main.LocalToolHandler.AimedBlock.ColorMaskHSV, Main.LocalToolHandler.AimedBlock.SkinSubtypeId); } else { paint = Main.LocalToolHandler.AimedPlayersPaint; } Main.Palette.GrabPaletteFromPaint(paint); } else { Main.Notifications.Show(0, "First aim at a block or player.", MyFontEnum.Red, 2000); } } } else { colorPickInputPressed = false; } }
bool SetColorAndSkin(PaintMaterial pickedMaterial, bool changeApply) { // in case of players with both ApplyColor and ApplySkin turned off. if (!pickedMaterial.ColorMask.HasValue && !pickedMaterial.Skin.HasValue) { Main.Notifications.Show(0, $"Target has no color or skin enabled.", MyFontEnum.Red, 3000); return(false); } PaintMaterial currentMaterial = GetLocalPaintMaterial(); if (currentMaterial.PaintEquals(pickedMaterial)) { Main.Notifications.Show(0, $"Color and skin already selected.", MyFontEnum.Debug, 2000); return(false); } bool success = false; if (pickedMaterial.ColorMask.HasValue) { if (changeApply) { LocalInfo.ApplyColor = true; } if (Utils.ColorMaskEquals(LocalInfo.SelectedColorMask, pickedMaterial.ColorMask.Value)) { Main.Notifications.Show(0, $"Color already selected.", MyFontEnum.Debug, 2000); } else { bool inPalette = false; for (int i = 0; i < LocalInfo.ColorsMasks.Count; i++) { if (Utils.ColorMaskEquals(LocalInfo.ColorsMasks[i], pickedMaterial.ColorMask.Value)) { inPalette = true; LocalInfo.SelectedColorSlot = i; MyAPIGateway.Session.Player.SelectedBuildColorSlot = i; Main.Notifications.Show(0, $"Color exists in slot [{(i + 1).ToString()}], selected.", MyFontEnum.Debug, 2000); break; } } if (!inPalette) { MyAPIGateway.Session.Player.ChangeOrSwitchToColor(pickedMaterial.ColorMask.Value); Main.NetworkLibHandler.PacketPaletteSetColor.Send(LocalInfo.SelectedColorSlot, pickedMaterial.ColorMask.Value); Main.Notifications.Show(0, $"Color slot [{(LocalInfo.SelectedColorSlot + 1).ToString()}] set to [{Utils.ColorMaskToString(pickedMaterial.ColorMask.Value)}]", MyFontEnum.Debug, 2000); } success = true; } } else { if (changeApply) { LocalInfo.ApplyColor = false; } } if (pickedMaterial.Skin.HasValue) { if (changeApply) { LocalInfo.ApplySkin = true; } if (LocalInfo.SelectedSkin != pickedMaterial.Skin.Value) { SkinInfo skin = GetSkinInfo(pickedMaterial.Skin.Value); if (skin != null) { if (!skin.LocallyOwned) { Main.Notifications.Show(1, $"Skin [{skin.Name}] is not owned, not selected.", MyFontEnum.Red, 2000); } else { LocalInfo.SelectedSkin = skin.SubtypeId; success = true; Main.Notifications.Show(1, $"Selected skin: [{skin.Name}]", MyFontEnum.Debug, 2000); } } } } else { if (changeApply) { LocalInfo.ApplySkin = false; } } return(success); }
public bool PaintEquals(PaintMaterial paintMaterial) { return((!ColorMask.HasValue || !paintMaterial.ColorMask.HasValue || Utils.ColorMaskEquals(ColorMask.Value, paintMaterial.ColorMask.Value)) && (!Skin.HasValue || !paintMaterial.Skin.HasValue || Skin.Value.Equals(paintMaterial.Skin.Value))); }
/// <summary> /// <param name="sync"></param> arg determines if it sends the paint request using the API, and automatically checks skin ownership. Must be false for mod-added skins. /// </summary> public void ReplaceColorInGrid(bool sync, IMyCubeGrid selectedGrid, BlockMaterial oldPaint, PaintMaterial paint, bool includeSubgrids, ulong originalSenderSteamId) { //long timeStart = Stopwatch.GetTimestamp(); ConnectedGrids.Clear(); if (includeSubgrids) { MyAPIGateway.GridGroups.GetGroup(selectedGrid, GridLinkTypeEnum.Mechanical, ConnectedGrids); } else { ConnectedGrids.Add(selectedGrid); } bool queueCheck = paint.Skin.HasValue; // only care if new paint affects skin //int total = 0; int affected = 0; foreach (IMyCubeGrid grid in ConnectedGrids) { MyCubeGrid internalGrid = (MyCubeGrid)grid; // avoiding GetCubeBlock() lookup by feeding MySlimBlock directly // must remain `var` because it's uses a prohibited type in the generic. var enumerator = internalGrid.CubeBlocks.GetEnumerator(); try { while (enumerator.MoveNext()) { IMySlimBlock block = enumerator.Current; BlockMaterial blockMaterial = new BlockMaterial(block); if (paint.Skin.HasValue && blockMaterial.Skin != oldPaint.Skin) { continue; } if (paint.ColorMask.HasValue && !Utils.ColorMaskEquals(blockMaterial.ColorMask, oldPaint.ColorMask)) { continue; } if (sync) { grid.SkinBlocks(block.Position, block.Position, paint.ColorMask, paint.Skin?.String); if (queueCheck) { queueCheck = false; // only check first block CheckSkinned[block] = new CheckData(paint.Skin.Value); // replace, in case they swap out skins quickly } } else { internalGrid.ChangeColorAndSkin(enumerator.Current, paint.ColorMask, paint.Skin); if (queueCheck) { queueCheck = false; // only check first block CheckSkinned.Remove(block); } } affected++; } } finally { enumerator.Dispose(); } //total += grid.CubeBlocks.Count; } if (CheckSkinned.Count > 0) { SetUpdateMethods(UpdateFlags.UPDATE_AFTER_SIM, true); } //long timeEnd = Stopwatch.GetTimestamp(); if (originalSenderSteamId == MyAPIGateway.Multiplayer.MyId) { Main.Notifications.Show(2, $"Replaced color for {affected.ToString()} blocks.", MyFontEnum.Debug, 5000); //double seconds = (timeEnd - timeStart) / (double)Stopwatch.Frequency; //if(affected == total) // Main.Notifications.Show(2, $"Replaced color for all {affected.ToString()} blocks in {(seconds * 1000).ToString("0.######")}ms", MyFontEnum.White, 5000); //else // Main.Notifications.Show(2, $"Replaced color for {affected.ToString()} of {total.ToString()} blocks in {(seconds * 1000).ToString("0.######")}ms", MyFontEnum.White, 5000); } ConnectedGrids.Clear(); }
Vector3I?MirrorPaint(bool sync, IMyCubeGrid grid, int axis, MirrorData mirrorPlanes, bool odd, Vector3I originalPosition, PaintMaterial paint, List <Vector3I> alreadyMirrored, ulong originalSenderSteamId) { Vector3I?mirrorPosition = null; switch (axis) { case 0: if (mirrorPlanes.X.HasValue) { mirrorPosition = originalPosition + new Vector3I(((mirrorPlanes.X.Value - originalPosition.X) * 2) - (odd ? 1 : 0), 0, 0); } break; case 1: if (mirrorPlanes.Y.HasValue) { mirrorPosition = originalPosition + new Vector3I(0, ((mirrorPlanes.Y.Value - originalPosition.Y) * 2) - (odd ? 1 : 0), 0); } break; case 2: if (mirrorPlanes.Z.HasValue) { mirrorPosition = originalPosition + new Vector3I(0, 0, ((mirrorPlanes.Z.Value - originalPosition.Z) * 2) + (odd ? 1 : 0)); // reversed on odd } break; } if (mirrorPosition.HasValue && originalPosition != mirrorPosition.Value && !alreadyMirrored.Contains(mirrorPosition.Value) && grid.CubeExists(mirrorPosition.Value)) { alreadyMirrored.Add(mirrorPosition.Value); PaintBlock(sync, grid, mirrorPosition.Value, paint, originalSenderSteamId); } return(mirrorPosition); }
/// <summary> /// <param name="sync"></param> arg determines if it sends the paint request using the API, and automatically checks skin ownership. Must be false for mod-added skins. /// </summary> public void PaintBlockSymmetry(bool sync, IMyCubeGrid grid, Vector3I gridPosition, PaintMaterial paint, MirrorData mirrorData, ulong originalSenderSteamId) { PaintBlock(sync, grid, gridPosition, paint, originalSenderSteamId); List <Vector3I> alreadyMirrored = Main.Caches.AlreadyMirrored; alreadyMirrored.Clear(); Vector3I?mirrorX = MirrorPaint(sync, grid, 0, mirrorData, mirrorData.OddX, gridPosition, paint, alreadyMirrored, originalSenderSteamId); // X Vector3I?mirrorY = MirrorPaint(sync, grid, 1, mirrorData, mirrorData.OddY, gridPosition, paint, alreadyMirrored, originalSenderSteamId); // Y Vector3I?mirrorZ = MirrorPaint(sync, grid, 2, mirrorData, mirrorData.OddZ, gridPosition, paint, alreadyMirrored, originalSenderSteamId); // Z Vector3I?mirrorYZ = null; if (mirrorX.HasValue && mirrorData.Y.HasValue) // XY { MirrorPaint(sync, grid, 1, mirrorData, mirrorData.OddY, mirrorX.Value, paint, alreadyMirrored, originalSenderSteamId); } if (mirrorX.HasValue && mirrorData.Z.HasValue) // XZ { MirrorPaint(sync, grid, 2, mirrorData, mirrorData.OddZ, mirrorX.Value, paint, alreadyMirrored, originalSenderSteamId); } if (mirrorY.HasValue && mirrorData.Z.HasValue) // YZ { mirrorYZ = MirrorPaint(sync, grid, 2, mirrorData, mirrorData.OddZ, mirrorY.Value, paint, alreadyMirrored, originalSenderSteamId); } if (mirrorData.X.HasValue && mirrorYZ.HasValue) // XYZ { MirrorPaint(sync, grid, 0, mirrorData, mirrorData.OddX, mirrorYZ.Value, paint, alreadyMirrored, originalSenderSteamId); } }