// multiplayer public void OnConnectedToServer() { if (MasterEngine.getInstance().EnableMultiplayer&& MasterEngine.getInstance().MultiplayerTrackPosition) { StartCoroutine(InitialPositionAndRangeUpdate()); } }
private void ApplyBlocks() // gets all valid voxel prefabs and applies them to the lBlocks array in the Engine GameObject { List <GameObject> voxels = new List <GameObject>(); int empty = 0; // count of empty items between non-empty items for (ushort i = 0; i < ushort.MaxValue; i++) { Object voxel = AssetDatabase.LoadAssetAtPath(GetBlockPath(i), typeof(Object)); if (voxel != null) { while (empty > 0) // add empty spaces { voxels.Add(null); empty--; } voxels.Add((GameObject)voxel); // add item } else { empty++; } } MasterEngine engine = EngineInstance.GetComponent <MasterEngine>(); engine.lBlocks = voxels.ToArray(); UnityEditor.PrefabUtility.ReplacePrefab(engine.gameObject, UnityEditor.PrefabUtility.GetPrefabParent(engine.gameObject), ReplacePrefabOptions.ConnectToPrefab); }
void DistributeChange(NetworkPlayer sender, int x, int y, int z, int chunkx, int chunky, int chunkz, int data, bool isChangeBlock) // sends a change in the voxel data to all clients // update server { ApplyOnServer(x, y, z, chunkx, chunky, chunkz, data, isChangeBlock); // the server can't send RPCs to itself so we'll need to call them directly // send to every client foreach (NetworkPlayer player in Network.connections) { if (player != Network.player) // skip server { if (MasterEngine.getInstance().MultiplayerTrackPosition == false || IsWithinRange(player, new Index(chunkx, chunky, chunkz))) // check if the change is within range of each player { if (EnableDebugLog) { Debug.Log("UniblocksServer: Sending voxel change to player " + player.ToString()); } if (isChangeBlock) { GetComponent <NetworkView>().RPC("ReceiveChangeBlock", player, sender, x, y, z, chunkx, chunky, chunkz, data); } else { GetComponent <NetworkView>().RPC("ReceivePlaceBlock", player, sender, x, y, z, chunkx, chunky, chunkz, data); } } } } }
public void InitializeGenerator() { // load seed if it's not loaded yet while (MasterEngine.getInstance().WorldSeed == 0) { MasterEngine.getInstance().GetSeed(); } seed = MasterEngine.getInstance().WorldSeed; // get chunk component chunk = GetComponent <Chunk>(); // generate data GenerateVoxelData(); // set empty chunk.Empty = true; foreach (ushort voxel in chunk.VoxelData) { if (voxel != 0) { chunk.Empty = false; break; } } // flag as done chunk.VoxelsDone = true; }
private void StartSpawnChunks(int originX, int originY, int originZ) { ChunkManager.SpawningChunks = true; Done = false; int range = MasterEngine.getInstance().ChunkSpawnDistance; StartCoroutine(SpawnMissingChunks(originX, originY, originZ, range)); }
IEnumerator InitialPositionAndRangeUpdate() { while (MasterEngine.getInstance().UniblocksNetwork == null) { yield return(new WaitForEndOfFrame()); } UniblocksClient.UpdatePlayerPosition(currentPos); UniblocksClient.UpdatePlayerRange(MasterEngine.getInstance().ChunkSpawnDistance); }
public void OnConnectedToServer() { Debug.Log("UniblocksClient: Connected to server."); if (MasterEngine.getInstance().EnableMultiplayer == false) { Debug.LogWarning("StarColony: Multiplayer is disabled. Unexpected behavior may occur."); } MasterEngine.getInstance().SaveVoxelData = false; // disable local saving for client }
public override void GenerateVoxelData() { int chunky = chunk.ChunkIndex.y; int SideLength = MasterEngine.getInstance().ChunkSideLength; for (int x = 0; x < SideLength; x++) { for (int y = 0; y < SideLength; y++) { for (int z = 0; z < SideLength; z++) // for all voxels in the chunk { Vector3 voxelPos = chunk.VoxelIndexToPosition(x, y, z); // get absolute position for the voxel voxelPos = new Vector3(voxelPos.x + seed, voxelPos.y, voxelPos.z + seed); // offset by seed float perlin1 = Mathf.PerlinNoise(voxelPos.x * 0.010f, voxelPos.z * 0.010f) * 70.1f; // major (mountains & big hills) float perlin2 = Mathf.PerlinNoise(voxelPos.x * 0.085f, voxelPos.z * 0.085f) * 9.1f; // minor (fine detail) int currentHeight = y + (SideLength * chunky); // get absolute height for the voxel bool setToGrass = false; // grass pass if (perlin1 > currentHeight) { if (perlin1 > perlin2 + currentHeight) { chunk.SetVoxelSimple(x, y, z, 2); // set grass setToGrass = true; } } // dirt pass currentHeight = currentHeight + 1; // offset dirt by 1 (since we want grass 1 block higher) if (perlin1 > currentHeight) { if (perlin1 > perlin2 + currentHeight) { chunk.SetVoxelSimple(x, y, z, 1); // set dirt setToGrass = false; } } // tree pass if (setToGrass && TreeCanFit(x, y, z)) // only add a tree if the current block has been set to grass and if there is room for the tree in the chunk { if (Random.Range(0.0f, 1.0f) < 0.01f) // 1% chance to add a tree { AddTree(x, y + 1, z); } } } } } }
public void Update() { if (MasterEngine.getInstance().SendCameraLookEvents) { CameraLookEvents(); } if (MasterEngine.getInstance().SendCursorEvents) { MouseCursorEvents(); } }
public bool CheckAllAdjacent(int x, int y, int z) // returns true if all adjacent voxels are solid { for (int direction = 0; direction < 6; direction++) { if (MasterEngine.getInstance().GetVoxelType(chunk.GetVoxel(chunk.GetAdjacentIndex(x, y, z, (Direction)direction))).VTransparency != Transparency.solid) { return(false); } } return(true); }
private void CameraLookEvents() { // first person camera var cam = Camera.main.transform; KeyValuePair <bool, RaycastHit> hitInfo = RaycastUtil.AABB(new Ray(cam.position, cam.forward), 3F); BlockInfo raycast = null; if (!hitInfo.Key) { return; } if (MasterEngine.getInstance().getVoxelEngine().raycastHasVoxel(hitInfo.Value)) { raycast = MasterEngine.getInstance().getVoxelEngine().getVoxelInfo(hitInfo.Value, 3f, false); } if (raycast != null) { // create a local copy of the hit voxel so we can call functions on it GameObject voxelObject = Instantiate(MasterEngine.getInstance().GetVoxelGameObject(raycast.GetVoxel())) as GameObject; // only execute this if the voxel actually has any events (either VoxelEvents component, or any component that inherits from it) if (voxelObject.GetComponent <VoxelEvents>() != null) { voxelObject.GetComponent <VoxelEvents>().OnLook(raycast); // for all mouse buttons, send events for (int i = 0; i < 3; i++) { if (Input.GetMouseButtonDown(i)) { voxelObject.GetComponent <VoxelEvents>().OnMouseDown(i, raycast); } if (Input.GetMouseButtonUp(i)) { voxelObject.GetComponent <VoxelEvents>().OnMouseUp(i, raycast); } if (Input.GetMouseButton(i)) { voxelObject.GetComponent <VoxelEvents>().OnMouseHold(i, raycast); } } } Destroy(voxelObject); } else { // disable selected block ui when no block is hit if (SelectedBlockGraphics != null) { SelectedBlockGraphics.GetComponent <Renderer>().enabled = false; } } }
bool TreeCanFit(int x, int y, int z) { if (x > 0 && x < MasterEngine.getInstance().ChunkSideLength - 1 && z > 0 && z < MasterEngine.getInstance().ChunkSideLength - 1 && y + 5 < MasterEngine.getInstance().ChunkSideLength) { return(true); } else { return(false); } }
void OnPlayerDisconnected(NetworkPlayer player) { if (MasterEngine.getInstance().MultiplayerTrackPosition) { PlayerPositions.Remove(player); PlayerChunkSpawnDistances.Remove(player); } if (EnableDebugLog) { Debug.Log("UniblocksServer: Player disconnected from server."); } }
public override void GenerateVoxelData() { int chunky = chunk.ChunkIndex.y; int SideLength = MasterEngine.getInstance().ChunkSideLength; // debug int random = Random.Range(0, 10); for (int x = 0; x < SideLength; x++) { for (int y = 0; y < SideLength; y++) { for (int z = 0; z < SideLength; z++) // for all voxels in the chunk { Vector3 voxelPos = chunk.VoxelIndexToPosition(x, y, z); // get absolute position for the voxel voxelPos = new Vector3(voxelPos.x + seed, voxelPos.y, voxelPos.z + seed); // offset by seed float perlin1 = Mathf.PerlinNoise(voxelPos.x * 0.010f, voxelPos.z * 0.010f) * 70.1f; // major (mountains & big hills) float perlin2 = Mathf.PerlinNoise(voxelPos.x * 0.085f, voxelPos.z * 0.085f) * 9.1f; // minor (fine detail) int currentHeight = y + (SideLength * chunky); // get absolute height for the voxel // grass pass if (perlin1 > currentHeight) { if (perlin1 > perlin2 + currentHeight) { chunk.SetVoxelSimple(x, y, z, 2); // set grass } } // dirt pass currentHeight = currentHeight + 1; // offset dirt by 1 (since we want grass 1 block higher) if (perlin1 > currentHeight) { if (perlin1 > perlin2 + currentHeight) { chunk.SetVoxelSimple(x, y, z, 1); // set dirt } } // debug if (random == 1) { //chunk.SetVoxelSimple(x,y,z, 3); // set stone or whatever } } } } }
private static void CreateRegionFile(Index index) // creates an empty region file { Directory.CreateDirectory(MasterEngine.getInstance().WorldPath); StreamWriter writer = new StreamWriter(GetRegionPath(index)); for (int i = 0; i < 999; i++) { writer.Write((char)ushort.MaxValue); } writer.Flush(); writer.Close(); }
// ==== Find Engine ===== private bool FindEngine() // returns false if engine not found, else true { foreach (Object obj in Object.FindObjectsOfType <MasterEngine>()) { if (obj != null) { MasterEngine engine = obj as MasterEngine; EngineInstance = engine.gameObject; return(true); } } return(false); }
public static GameObject SpawnChunk(Index index) // spawns a single chunk (only if it's not already spawned) { GameObject chunk = ChunkManager.GetChunk(index); if (chunk == null) { return(MasterEngine.getInstance().ChunkManagerInstance.DoSpawnChunk(index)); } else { return(chunk); } }
private void SaveData() { if (MasterEngine.getInstance().SaveVoxelData == false) { Debug.LogWarning("StarColony: Saving is disabled. You can enable it in the Engine Settings."); return; } if (Application.isWebPlayer == false) { GetComponent <ChunkDataFiles>().SaveData(); } }
private void MouseCursorEvents() { // cursor position KeyValuePair <bool, RaycastHit> hitInfo = RaycastUtil.AABB(Camera.main.ScreenPointToRay(Input.mousePosition), 2F); //Vector3 pos = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, 10.0f); BlockInfo raycast = null; if (MasterEngine.getInstance().getVoxelEngine().raycastHasVoxel(hitInfo.Value)) { raycast = MasterEngine.getInstance().getVoxelEngine().getVoxelInfo(hitInfo.Value, 2F, false); } if (raycast != null) { // create a local copy of the hit voxel so we can call functions on it GameObject voxelObject = Instantiate(MasterEngine.getInstance().GetVoxelGameObject(raycast.GetVoxel())) as GameObject; // only execute this if the voxel actually has any events (either VoxelEvents component, or any component that inherits from it) if (voxelObject.GetComponent <VoxelEvents>() != null) { voxelObject.GetComponent <VoxelEvents>().OnLook(raycast); // for all mouse buttons, send events for (int i = 0; i < 3; i++) { if (Input.GetMouseButtonDown(i)) { voxelObject.GetComponent <VoxelEvents>().OnMouseDown(i, raycast); } if (Input.GetMouseButtonUp(i)) { voxelObject.GetComponent <VoxelEvents>().OnMouseUp(i, raycast); } if (Input.GetMouseButton(i)) { voxelObject.GetComponent <VoxelEvents>().OnMouseHold(i, raycast); } } } Destroy(voxelObject); } else { // disable selected block ui when no block is hit if (SelectedBlockGraphics != null) { SelectedBlockGraphics.GetComponent <Renderer>().enabled = false; } } }
void Update() { // keyboard shortcuts if (Input.GetKeyDown("space") && Time.realtimeSinceStartup > 3.0f) { GetComponent <CharacterMotor>().enabled = true; } if (Input.GetKeyDown("v")) { MasterEngine.getInstance().SaveWorldInstant(); } if (Input.GetKeyDown("f")) { if (Flashlight.GetComponent <Light>().enabled == true) { Flashlight.GetComponent <Light>().enabled = false; } else { Flashlight.GetComponent <Light>().enabled = true; } } if (Input.GetKeyDown("t")) { if (Torch.GetComponent <Light>().enabled == true) { Torch.GetComponent <Light>().enabled = false; } else { Torch.GetComponent <Light>().enabled = true; } } // world save timer if (saveTimer < 0.0f) { saveTimer = 60.0f; MasterEngine.getInstance().SaveWorld(); } else { saveTimer -= Time.deltaTime; } }
public void Update() { // change held block with 1-9 keys for (ushort i = 0; i < 10; i++) { if (Input.GetKeyDown(i.ToString())) { if (MasterEngine.getInstance().GetVoxelType(i) != null) { ExampleInventory.HeldBlock = i; Debug.Log("Held block is now:" + i.ToString()); } } } }
private Dictionary <NetworkPlayer, int> PlayerChunkSpawnDistances; // chunk spawn distance for each player void Awake() { if (MasterEngine.getInstance().EnableMultiplayer == false) { Debug.LogWarning("StarColony: Multiplayer is disabled. Unexpected behavior may occur."); } MasterEngine.getInstance().UniblocksNetwork = this.gameObject; ResetPlayerData(); if (Network.isServer) { Debug.Log("UniblocksServer: Server initialized."); } }
// ===== save data void Update() { if (AutosaveTime > 0.0001f) { if (autosaveTimer >= AutosaveTime) { autosaveTimer = 0; MasterEngine.getInstance().SaveWorld(); } else { autosaveTimer += Time.deltaTime; } } }
public static int CurrentChunkDataRequests; // how many chunk requests are currently queued in the server for this client. Increased by 1 every time a chunk requests data, and reduced by 1 when a chunk receives data. IEnumerator RequestVoxelData() // waits until we're connected to a server and then sends a request for voxel data for this chunk to the server { while (!Network.isClient) { Chunk.CurrentChunkDataRequests = 0; // reset the counter if we're not connected yield return(new WaitForEndOfFrame()); } while (MasterEngine.getInstance().MaxChunkDataRequests != 0 && Chunk.CurrentChunkDataRequests >= MasterEngine.getInstance().MaxChunkDataRequests) { yield return(new WaitForEndOfFrame()); } Chunk.CurrentChunkDataRequests++; MasterEngine.getInstance().UniblocksNetwork.GetComponent <NetworkView>().RPC("SendVoxelData", RPCMode.Server, Network.player, ChunkIndex.x, ChunkIndex.y, ChunkIndex.z); }
public static void ChangeBlock(BlockInfo voxelInfo, ushort data) { // multiplayer - send change to server if (MasterEngine.getInstance().EnableMultiplayer) { MasterEngine.getInstance().UniblocksNetwork.GetComponent <UniblocksClient>().SendChangeBlock(voxelInfo, data); return; } voxelInfo.chunk.SetVoxel(voxelInfo.index, data, true); GameObject voxelObject = Instantiate(getVoxelGameObject(data)) as GameObject; if (voxelObject.GetComponent <VoxelEvents>() != null) { voxelObject.GetComponent <VoxelEvents>().OnBlockChange(voxelInfo); } Destroy(voxelObject); }
void Start() { targetFrameDuration = 1f / MasterEngine.getInstance().TargetFPS; ChunkManager.Chunks = new Dictionary <string, Chunk>(); ChunkManager.ChunkUpdateQueue = new List <Chunk>(); frameStopwatch = new Stopwatch(); MasterEngine.getInstance().ChunkScale = ChunkObject.transform.localScale; ChunkObject.GetComponent <Chunk>().MeshContainer.transform.localScale = ChunkObject.transform.localScale; // set correct scale of trigger collider and additional mesh collider ChunkObject.GetComponent <Chunk>().ChunkCollider.transform.localScale = ChunkObject.transform.localScale; Done = true; ChunkManager.SpawningChunks = false; ChunkManager.Initialized = true; }
public static GameObject SpawnChunkFromServer(Index index) // spawns a chunk and disables mesh generation and enables timeout (used by the server in multiplayer) { GameObject chunk = ChunkManager.GetChunk(index); if (chunk == null) { chunk = MasterEngine.getInstance().ChunkManagerInstance.DoSpawnChunk(index); Chunk chunkComponent = chunk.GetComponent <Chunk>(); chunkComponent.EnableTimeout = true; chunkComponent.DisableMesh = true; return(chunk); } else { return(chunk); // don't disable mesh generation and don't enable timeout for chunks that are already spawned } }
private bool CheckAdjacent(int x, int y, int z, Direction direction, Transparency transparency) // returns true if a face should be spawned { Index index = chunk.GetAdjacentIndex(x, y, z, direction); ushort adjacentVoxel = chunk.GetVoxel(index.x, index.y, index.z); if (adjacentVoxel == ushort.MaxValue) // if the neighbor chunk is missing { if (MasterEngine.getInstance().ShowBorderFaces || direction == Direction.up) { return(true); } else { return(false); } } Transparency result = MasterEngine.getInstance().GetVoxelType(adjacentVoxel).VTransparency; // get the transparency of the adjacent voxel // parse the result (taking into account the transparency of the adjacent block as well as the one doing this check) if (transparency == Transparency.transparent) { if (result == Transparency.transparent) { return(false); // don't draw a transparent block next to another transparent block } else { return(true); // draw a transparent block next to a solid or semi-transparent } } else { if (result == Transparency.solid) { return(false); // don't draw a solid block or a semi-transparent block next to a solid block } else { return(true); // draw a solid block or a semi-transparent block next to both transparent and semi-transparent } } }
public static void SaveAllChunksInstant() // writes data from TempChunkData into region files { if (!MasterEngine.getInstance().SaveVoxelData) { Debug.LogWarning("StarColony: Saving is disabled. You can enable it in the Engine Settings."); return; } // for each chunk object, save data to memory foreach (Chunk chunk in ChunkManager.Chunks.Values) { chunk.gameObject.GetComponent <ChunkDataFiles>().SaveData(); } // write data to disk ChunkDataFiles.WriteLoadedChunks(); Debug.Log("StarColony: World saved successfully. (Instant)"); }
public static void DestroyBlock(BlockInfo voxelInfo) { // multiplayer - send change to server if (MasterEngine.getInstance().EnableMultiplayer) { MasterEngine.getInstance().UniblocksNetwork.GetComponent <UniblocksClient>().SendPlaceBlock(voxelInfo, 0); } // single player - apply change locally else { GameObject voxelObject = Instantiate(getVoxelGameObject(voxelInfo.GetVoxel())) as GameObject; if (voxelObject.GetComponent <VoxelEvents>() != null) { voxelObject.GetComponent <VoxelEvents>().OnBlockDestroy(voxelInfo); } voxelInfo.chunk.SetVoxel(voxelInfo.index, 0, true); Destroy(voxelObject); } }