Quantum-Engineering/BuildController.cs

465 lines
20 KiB
C#

using System.Collections;
using UnityEngine;
using System.Net;
public class BuildController : MonoBehaviour
{
private PlayerController playerController;
private GameManager gameManager;
public BlockDictionary blockDictionary;
private LineRenderer dirLine;
public Material lineMat;
public GameObject builtObjects;
public AudioClip singleBuildClip;
public AudioClip multiBuildClip;
public bool autoAxis;
private Coroutine buildBlockCoroutine;
//! Called by unity engine on start up to initialize variables
public void Start()
{
playerController = GetComponent<PlayerController>();
gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
blockDictionary = new BlockDictionary(playerController);
builtObjects = GameObject.Find("BuiltObjects");
}
//! Called once per frame by unity engine
public void Update()
{
if (!playerController.stateManager.Busy())
{
if (playerController.building == true)
{
if (playerController.separatedBlocks == false)
{
if (gameManager.working == false)
{
gameManager.meshManager.SeparateBlocks(transform.position, "all", true);
playerController.separatedBlocks = true;
}
else
{
playerController.requestedChunkLoad = true;
}
playerController.buildStartPosition = transform.position;
}
else
{
float distance = Vector3.Distance(transform.position, playerController.buildStartPosition);
if (distance > gameManager.chunkSize * 0.75f)
{
if (gameManager.working == false)
{
gameManager.meshManager.SeparateBlocks(transform.position, "all", true);
playerController.separatedBlocks = true;
}
else
{
playerController.requestedChunkLoad = true;
}
playerController.buildStartPosition = transform.position;
}
}
if (playerController.buildObject == null)
{
CreateBuildObject();
}
else
{
if (Physics.Raycast(Camera.main.gameObject.transform.position, Camera.main.gameObject.transform.forward, out RaycastHit hit, gameManager.chunkSize))
{
float distance = Vector3.Distance(transform.position, playerController.buildObject.transform.position);
Material buildObjectMaterial = playerController.buildObject.GetComponent<MeshRenderer>().material;
buildObjectMaterial.color = distance > gameManager.chunkSize * 0.75f ? Color.red : Color.white;
if (hit.transform.gameObject.tag == "Built" || hit.transform.gameObject.tag == "Machine")
{
if (autoAxis == true)
{
AutoSelectBuildAxis(hit);
}
SetupBuildAxis(hit);
}
else
{
if (autoAxis == true)
{
playerController.cubeloc = "up";
}
SetupFreePlacement(hit);
}
}
if (Physics.Raycast(Camera.main.gameObject.transform.position, Camera.main.gameObject.transform.forward, out RaycastHit buildHit, gameManager.chunkSize * 0.75f))
{
if (buildHit.collider.gameObject.tag != "CombinedMesh")
{
playerController.buildObject.GetComponent<MeshRenderer>().material.color = Color.white;
if (cInput.GetKeyDown("Place Object"))
{
if (blockDictionary.machineDictionary.ContainsKey(playerController.buildType))
{
BuildMachine(playerController.buildType, hit);
}
else
{
BuildBlock(playerController.buildType);
}
}
}
else
{
playerController.buildObject.GetComponent<MeshRenderer>().material.color = Color.red;
if (gameManager.working == false)
{
gameManager.meshManager.SeparateBlocks(buildHit.point, "all", true);
}
else
{
playerController.requestedChunkLoad = true;
}
}
}
}
}
else if (playerController.buildObject != null)
{
Destroy(playerController.buildObject);
}
}
}
//! Creates the block placement cursor.
private void CreateBuildObject()
{
playerController.buildObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
playerController.buildObject.transform.localScale = new Vector3(5, 5, 5);
playerController.buildObject.transform.position = Camera.main.gameObject.transform.position + Camera.main.gameObject.transform.forward * 5;
playerController.buildObject.GetComponent<Renderer>().material = playerController.constructionMat;
playerController.buildObject.GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
Destroy(playerController.buildObject.GetComponent<Collider>());
dirLine = playerController.buildObject.AddComponent<LineRenderer>();
dirLine.material = lineMat;
dirLine.startWidth = 0.2f;
dirLine.endWidth = 0.2f;
dirLine.loop = true;
dirLine.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
dirLine.SetPosition(0, playerController.buildObject.transform.position);
Vector3 dirVector = playerController.buildObject.transform.position + playerController.buildObject.transform.forward * 4;
dirLine.SetPosition(1, dirVector);
dirLine.enabled = true;
}
//! Automatically selects build axis based on raycast.
private void AutoSelectBuildAxis(RaycastHit buildHit)
{
Vector3 hitPoint = buildHit.point;
Vector3 blockPos = buildHit.collider.transform.position;
float xDif = hitPoint.x - blockPos.x;
float yDif = hitPoint.y - blockPos.y;
float zDif = hitPoint.z - blockPos.z;
float xnDif = blockPos.x - hitPoint.x;
float ynDif = blockPos.y - hitPoint.y;
float znDif = blockPos.z - hitPoint.z;
if (hitPoint.x > blockPos.x)
{
if (xDif > yDif && xDif > zDif)
playerController.cubeloc = "left";
}
if (hitPoint.x < blockPos.x)
{
if (xnDif > ynDif && xnDif > znDif)
playerController.cubeloc = "right";
}
if (hitPoint.y > blockPos.y)
{
if (yDif > xDif && yDif > zDif)
playerController.cubeloc = "up";
}
if (hitPoint.y < blockPos.y)
{
if (ynDif > xnDif && ynDif > znDif)
playerController.cubeloc = "down";
}
if (hitPoint.z > blockPos.z)
{
if (zDif > xDif && zDif > yDif)
playerController.cubeloc = "front";
}
if (hitPoint.z < blockPos.z)
{
if (znDif > xnDif && znDif > ynDif)
playerController.cubeloc = "back";
}
}
//! Changes the axis along which blocks will be placed.
public void ChangeBuildAxis()
{
if (playerController.cubeloc == "up")
{
playerController.cubeloc = "down";
}
else if (playerController.cubeloc == "down")
{
playerController.cubeloc = "left";
}
else if (playerController.cubeloc == "left")
{
playerController.cubeloc = "right";
}
else if (playerController.cubeloc == "right")
{
playerController.cubeloc = "front";
}
else if (playerController.cubeloc == "front")
{
playerController.cubeloc = "back";
}
else if (playerController.cubeloc == "back")
{
playerController.cubeloc = "up";
}
}
//! Implements the current build axis.
private void SetupBuildAxis(RaycastHit hit)
{
if (gameManager.working == false)
{
Vector3 placementPoint = hit.transform.position;
Quaternion placementRotation;
Vector3 dirVector;
if (playerController.cubeloc == "up")
{
placementPoint = new Vector3(hit.transform.position.x, hit.transform.position.y + 5, hit.transform.position.z);
}
else if (playerController.cubeloc == "down")
{
placementPoint = new Vector3(hit.transform.position.x, hit.transform.position.y - 5, hit.transform.position.z);
}
else if (playerController.cubeloc == "left")
{
placementPoint = new Vector3(hit.transform.position.x + 5, hit.transform.position.y, hit.transform.position.z);
}
else if (playerController.cubeloc == "right")
{
placementPoint = new Vector3(hit.transform.position.x - 5, hit.transform.position.y, hit.transform.position.z);
}
else if (playerController.cubeloc == "front")
{
placementPoint = new Vector3(hit.transform.position.x, hit.transform.position.y, hit.transform.position.z + 5);
}
else if (playerController.cubeloc == "back")
{
placementPoint = new Vector3(hit.transform.position.x, hit.transform.position.y, hit.transform.position.z - 5);
}
placementRotation = playerController.buildObject.transform.rotation;
playerController.buildObject.transform.position = placementPoint;
playerController.buildObject.transform.rotation = placementRotation;
dirLine.SetPosition(0, playerController.buildObject.transform.position);
dirVector = playerController.buildObject.transform.position + playerController.buildObject.transform.forward * 4;
dirLine.SetPosition(1, dirVector);
}
}
//! Prepares cursor for free block placement, ie: not attached to another block.
private void SetupFreePlacement(RaycastHit hit)
{
Vector3 placementPoint = new Vector3(hit.point.x, (hit.point.y + 2.4f), hit.point.z);
Quaternion placementRotation = playerController.buildObject.transform.rotation;
playerController.buildObject.transform.position = placementPoint;
playerController.buildObject.transform.rotation = placementRotation;
dirLine.SetPosition(0, playerController.buildObject.transform.position);
Vector3 dirVector = playerController.buildObject.transform.position + playerController.buildObject.transform.forward * 4;
dirLine.SetPosition(1, dirVector);
}
//! Places a machine in the world.
private void BuildMachine(string type, RaycastHit hit)
{
bool foundItems = false;
gameManager.undoBlocks.Clear();
foreach (InventorySlot slot in playerController.playerInventory.inventory)
{
if (foundItems == false)
{
if (slot.amountInSlot > 0)
{
if (slot.typeInSlot.Equals(type))
{
foundItems = true;
bool flag = true;
if (type.Equals("Rail Cart"))
{
if (hit.collider.gameObject.GetComponent<RailCartHub>() != null)
{
flag = true;
}
else
{
playerController.invalidRailCartPlacement = true;
flag = false;
}
}
else if (type.Equals("Auger"))
{
if (hit.collider.gameObject.tag.Equals("Landscape"))
{
flag = true;
}
else
{
playerController.invalidAugerPlacement = true;
flag = false;
}
}
if (flag == true)
{
GameObject t = blockDictionary.machineDictionary[type];
Vector3 pos = playerController.buildObject.transform.position;
Quaternion rot = playerController.buildObject.transform.rotation;
GameObject obj = Instantiate(t, pos, rot);
if (obj.GetComponent<RailCart>() != null)
{
obj.GetComponent<RailCart>().target = hit.collider.gameObject;
}
if (obj.GetComponent<ModMachine>() != null)
{
obj.GetComponent<ModMachine>().machineName = type;
}
if (obj.GetComponent<UniversalConduit>() != null)
{
obj.GetComponent<UniversalConduit>().range = playerController.defaultRange;
}
if (obj.GetComponent<PowerConduit>() != null)
{
obj.GetComponent<PowerConduit>().range = playerController.defaultRange;
}
if (obj.GetComponent<DarkMatterConduit>() != null)
{
obj.GetComponent<DarkMatterConduit>().range = playerController.defaultRange;
}
if (obj.GetComponent<RailCartHub>() != null)
{
obj.GetComponent<RailCartHub>().range = playerController.defaultRange;
}
gameManager.undoBlocks.Add(new GameManager.Block(type, obj));
slot.amountInSlot -= 1;
playerController.builderSound.clip = singleBuildClip;
playerController.builderSound.Play();
if (PlayerPrefsX.GetPersistentBool("multiplayer") == true)
{
UpdateNetwork(0,type,pos, obj.transform.rotation);
}
}
}
if (slot.amountInSlot == 0)
{
slot.typeInSlot = "nothing";
}
}
}
}
if (foundItems == false)
{
playerController.PlayMissingItemsSound();
}
}
//! Sends instantiated block info to the server in multiplayer games.
private void UpdateNetwork(int destroy, string type, Vector3 pos, Quaternion rot)
{
using(WebClient client = new WebClient())
{
System.Uri uri = new System.Uri(PlayerPrefs.GetString("serverURL") + "/blocks");
string position = Mathf.Round(pos.x) + "," + Mathf.Round(pos.y) + "," + Mathf.Round(pos.z);
string rotation = Mathf.Round(rot.x) + "," + Mathf.Round(rot.y) + "," + Mathf.Round(rot.z) + "," + Mathf.Round(rot.w);
client.UploadStringAsync(uri, "POST", "@" + destroy + ":" + type + ":" + position + ":" + rotation);
}
}
private void BuildBlock(string type)
{
gameManager.undoBlocks.Clear();
buildBlockCoroutine = StartCoroutine(BuildBlockCoroutine(type));
}
//! Places standard building blocks in the world.
private IEnumerator BuildBlockCoroutine(string type)
{
bool foundItems = false;
foreach (InventorySlot slot in playerController.playerInventory.inventory)
{
if (foundItems == false)
{
if (slot.amountInSlot >= playerController.buildMultiplier)
{
if (slot.typeInSlot.Equals(type))
{
foundItems = true;
int h = 0;
Vector3 origin = playerController.buildObject.transform.position;
string direction = playerController.cubeloc;
Quaternion rotation = playerController.buildObject.transform.rotation;
Vector3 multiBuildPlacement = playerController.buildObject.transform.position;
slot.amountInSlot -= playerController.buildMultiplier;
for (int i = 0; i < playerController.buildMultiplier; i++)
{
if (direction == "up")
{
multiBuildPlacement = new Vector3(origin.x, origin.y + h, origin.z);
}
if (direction == "down")
{
multiBuildPlacement = new Vector3(origin.x, origin.y - h, origin.z);
}
if (direction == "left")
{
multiBuildPlacement = new Vector3(origin.x + h, origin.y, origin.z);
}
if (direction == "right")
{
multiBuildPlacement = new Vector3(origin.x - h, origin.y, origin.z);
}
if (direction == "front")
{
multiBuildPlacement = new Vector3(origin.x, origin.y, origin.z + h);
}
if (direction == "back")
{
multiBuildPlacement = new Vector3(origin.x, origin.y, origin.z - h);
}
h += 5;
GameObject obj = Instantiate(blockDictionary.blockDictionary[type], multiBuildPlacement, rotation);
if (obj.GetComponent<ModBlock>() != null)
{
obj.GetComponent<ModBlock>().blockName = type;
}
obj.transform.parent = builtObjects.transform;
gameManager.undoBlocks.Add(new GameManager.Block(type, obj));
playerController.builderSound.clip = playerController.buildMultiplier > 1 ? multiBuildClip : singleBuildClip;
playerController.builderSound.Play();
if (PlayerPrefsX.GetPersistentBool("multiplayer") == true)
{
UpdateNetwork(0, type, obj.transform.position, obj.transform.rotation);
}
yield return null;
}
}
if (slot.amountInSlot == 0)
{
slot.typeInSlot = "nothing";
}
}
}
}
if (foundItems == false)
{
playerController.PlayMissingItemsSound();
}
}
}