1 /**
2 Copyright: Copyright (c) 2015-2016 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module voxelman.worldinteraction.plugin;
8 
9 import std.experimental.logger;
10 import core.time;
11 
12 import pluginlib;
13 import voxelman.core.config;
14 
15 import voxelman.core.events;
16 import voxelman.core.packets;
17 import voxelman.storage.coordinates;
18 
19 import voxelman.input.plugin;
20 import voxelman.eventdispatcher.plugin;
21 import voxelman.graphics.plugin;
22 import voxelman.client.plugin;
23 
24 
25 shared static this()
26 {
27 	pluginRegistry.regClientPlugin(new WorldInteractionPlugin);
28 }
29 
30 class WorldInteractionPlugin : IPlugin
31 {
32 	ClientPlugin clientPlugin;
33 	EventDispatcherPlugin evDispatcher;
34 	GraphicsPlugin graphics;
35 
36 	// Cursor
37 	bool cursorHit;
38 	BlockWorldPos blockPos;
39 	ivec3 hitNormal;
40 
41 	// Cursor rendering stuff
42 	vec3 cursorPos, cursorSize = vec3(1.02, 1.02, 1.02);
43 	vec3 lineStart, lineEnd;
44 	bool traceVisible;
45 	bool showCursor = true;
46 	vec3 hitPosition;
47 	Duration cursorTraceTime;
48 	Batch traceBatch;
49 	Batch hitBatch;
50 
51 	mixin IdAndSemverFrom!(voxelman.worldinteraction.plugininfo);
52 
53 	override void init(IPluginManager pluginman)
54 	{
55 		clientPlugin = pluginman.getPlugin!ClientPlugin;
56 		evDispatcher = pluginman.getPlugin!EventDispatcherPlugin;
57 		graphics = pluginman.getPlugin!GraphicsPlugin;
58 
59 		evDispatcher.subscribeToEvent(&onUpdateEvent);
60 		evDispatcher.subscribeToEvent(&drawDebug);
61 	}
62 
63 	void onUpdateEvent(ref UpdateEvent event)
64 	{
65 		traceCursor();
66 		drawDebugCursor();
67 	}
68 
69 	void placeBlock(BlockType blockId)
70 	{
71 		if (clientPlugin.chunkMan.blockMan.blocks[blockId].isVisible)
72 		{
73 			blockPos.vector += hitNormal;
74 		}
75 
76 		//infof("hit %s, blockPos %s, hitPosition %s, hitNormal %s\ntime %s",
77 		//	cursorHit, blockPos, hitPosition, hitNormal,
78 		//	cursorTraceTime.formatDuration);
79 
80 		cursorPos = vec3(blockPos.vector) - vec3(0.005, 0.005, 0.005);
81 		lineStart = graphics.camera.position;
82 		lineEnd = graphics.camera.position + graphics.camera.target * 40;
83 
84 		if (cursorHit)
85 		{
86 			hitBatch = traceBatch;
87 			traceBatch = Batch();
88 
89 			traceVisible = true;
90 			clientPlugin.connection.send(PlaceBlockPacket(blockPos.vector, blockId));
91 		}
92 		else
93 		{
94 			traceVisible = false;
95 		}
96 	}
97 
98 	BlockType pickBlock()
99 	{
100 		return clientPlugin.worldAccess.getBlock(blockPos);
101 	}
102 
103 	void traceCursor()
104 	{
105 		StopWatch sw;
106 		sw.start();
107 
108 		auto isBlockSolid = (ivec3 blockWorldPos) {
109 			auto block = clientPlugin.worldAccess.getBlock(BlockWorldPos(blockWorldPos));
110 			return clientPlugin.chunkMan
111 				.blockMan
112 				.blocks[block]
113 				.isVisible;
114 		};
115 
116 		traceBatch.reset();
117 
118 		cursorHit = traceRay(
119 			isBlockSolid,
120 			graphics.camera.position,
121 			graphics.camera.target,
122 			200.0, // max distance
123 			hitPosition,
124 			hitNormal,
125 			traceBatch);
126 
127 		blockPos = BlockWorldPos(hitPosition);
128 		cursorTraceTime = cast(Duration)sw.peek;
129 	}
130 
131 	void drawDebugCursor()
132 	{
133 		if (traceVisible)
134 		{
135 			traceBatch.putCube(cursorPos, cursorSize, Colors.black, false);
136 			traceBatch.putLine(lineStart, lineEnd, Colors.black);
137 		}
138 
139 		if (showCursor)
140 		{
141 			graphics.debugBatch.putCube(
142 				vec3(blockPos.vector) - vec3(0.005, 0.005, 0.005),
143 				cursorSize, Colors.red, false);
144 			graphics.debugBatch.putCube(
145 				vec3(blockPos.vector+hitNormal) - vec3(0.005, 0.005, 0.005),
146 				cursorSize, Colors.blue, false);
147 		}
148 	}
149 
150 	void drawDebug(ref Render1Event event)
151 	{
152 		//graphics.chunkShader.bind;
153 		//graphics.draw(hitBatch);
154 		//graphics.chunkShader.unbind;
155 	}
156 }