1 /** 2 Copyright: Copyright (c) 2015-2018 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 voxelman.log; 10 import core.time; 11 import core.time : MonoTime, Duration; 12 13 import pluginlib; 14 import voxelman.math; 15 import voxelman.core.config; 16 import voxelman.geometry.gridraytrace : traceRay; 17 import voxelman.world.block; 18 19 import voxelman.core.events; 20 import voxelman.core.packets; 21 import voxelman.world.storage.coordinates; 22 import voxelman.world.storage.worldbox; 23 import voxelman.world.blockentity.blockentityaccess; 24 25 import voxelman.block.plugin; 26 import voxelman.eventdispatcher.plugin; 27 import voxelman.graphics.plugin; 28 import voxelman.input.plugin; 29 import voxelman.net.plugin; 30 import voxelman.world.clientworld; 31 32 33 enum cursorSize = vec3(1.02, 1.02, 1.02); 34 enum cursorOffset = vec3(0.01, 0.01, 0.01); 35 36 class WorldInteractionPlugin : IPlugin 37 { 38 NetClientPlugin connection; 39 EventDispatcherPlugin evDispatcher; 40 GraphicsPlugin graphics; 41 BlockPluginClient blockPlugin; 42 ClientWorld clientWorld; 43 44 vec3 cameraPos() { return graphics.camera.position; } 45 vec3 cameraTraget() { return graphics.camera.target; } 46 47 // Cursor 48 bool cursorHit; 49 bool cameraInSolidBlock; 50 BlockWorldPos blockPos; 51 BlockWorldPos sideBlockPos; // blockPos + hitNormal 52 ivec3 hitNormal; 53 54 // Cursor rendering stuff 55 vec3 cursorPos; 56 vec3 lineStart, lineEnd; 57 bool traceVisible; 58 ivec3 hitPosition; 59 Duration cursorTraceTime; 60 Batch traceBatch; 61 Batch hitBatch; 62 63 mixin IdAndSemverFrom!"voxelman.worldinteraction.plugininfo"; 64 65 override void init(IPluginManager pluginman) 66 { 67 connection = pluginman.getPlugin!NetClientPlugin; 68 blockPlugin = pluginman.getPlugin!BlockPluginClient; 69 evDispatcher = pluginman.getPlugin!EventDispatcherPlugin; 70 graphics = pluginman.getPlugin!GraphicsPlugin; 71 clientWorld = pluginman.getPlugin!ClientWorld; 72 73 evDispatcher.subscribeToEvent(&onUpdateEvent); 74 evDispatcher.subscribeToEvent(&drawDebug); 75 } 76 77 void onUpdateEvent(ref UpdateEvent event) 78 { 79 traceCursor(); 80 drawDebugCursor(); 81 } 82 83 BlockIdAndMeta pickBlock() 84 { 85 return clientWorld.worldAccess.getBlockIdAndMeta(blockPos); 86 } 87 88 void fillBox(WorldBox box, BlockId blockId, BlockMetadata blockMeta = 0) 89 { 90 connection.send(FillBlockBoxPacket(box, blockId, blockMeta)); 91 } 92 93 void traceCursor() 94 { 95 MonoTime startTime = MonoTime.currTime; 96 97 traceBatch.reset(); 98 99 cursorHit = traceRay( 100 &clientWorld.isBlockSolid, 101 graphics.camera.position, 102 graphics.camera.target, 103 600.0, // max distance 104 hitPosition, 105 hitNormal, 106 traceBatch); 107 108 if (cursorHit) { 109 import std.math : floor; 110 auto camPos = graphics.camera.position; 111 auto camBlock = ivec3(cast(int)floor(camPos.x), cast(int)floor(camPos.y), cast(int)floor(camPos.z)); 112 cameraInSolidBlock = BlockWorldPos(camBlock, 0) == BlockWorldPos(hitPosition, 0); 113 } else { 114 cameraInSolidBlock = false; 115 } 116 117 blockPos = BlockWorldPos(hitPosition, clientWorld.currentDimension); 118 sideBlockPos = BlockWorldPos(blockPos.xyz + hitNormal, clientWorld.currentDimension); 119 cursorTraceTime = MonoTime.currTime - startTime; 120 } 121 122 void drawDebugCursor() 123 { 124 if (traceVisible) 125 { 126 traceBatch.putCube(cursorPos, cursorSize, Colors.black, false); 127 traceBatch.putLine(lineStart, lineEnd, Colors.black); 128 } 129 } 130 131 void drawCursor(BlockWorldPos block, Color4ub color) 132 { 133 if (!cameraInSolidBlock && cursorHit) 134 { 135 graphics.debugBatch.putCube( 136 vec3(block.xyz) - cursorOffset, 137 cursorSize, color, false); 138 } 139 } 140 141 void drawDebug(ref RenderSolid3dEvent event) 142 { 143 //graphics.draw(hitBatch); 144 } 145 }