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 import std.datetime : StopWatch; 12 13 import pluginlib; 14 import voxelman.math; 15 import voxelman.core.config; 16 import voxelman.utils.trace : traceRay; 17 import voxelman.block.utils; 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.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 shared static this() 34 { 35 pluginRegistry.regClientPlugin(new WorldInteractionPlugin); 36 } 37 38 enum cursorSize = vec3(1.02, 1.02, 1.02); 39 enum cursorOffset = vec3(0.01, 0.01, 0.01); 40 41 class WorldInteractionPlugin : IPlugin 42 { 43 NetClientPlugin connection; 44 EventDispatcherPlugin evDispatcher; 45 GraphicsPlugin graphics; 46 BlockPluginClient blockPlugin; 47 ClientWorld clientWorld; 48 49 // Cursor 50 bool cursorHit; 51 bool cameraInSolidBlock; 52 BlockWorldPos blockPos; 53 BlockWorldPos sideBlockPos; // blockPos + hitNormal 54 ivec3 hitNormal; 55 56 // Cursor rendering stuff 57 vec3 cursorPos; 58 vec3 lineStart, lineEnd; 59 bool traceVisible; 60 vec3 hitPosition; 61 Duration cursorTraceTime; 62 Batch traceBatch; 63 Batch hitBatch; 64 65 mixin IdAndSemverFrom!(voxelman.worldinteraction.plugininfo); 66 67 override void init(IPluginManager pluginman) 68 { 69 connection = pluginman.getPlugin!NetClientPlugin; 70 blockPlugin = pluginman.getPlugin!BlockPluginClient; 71 evDispatcher = pluginman.getPlugin!EventDispatcherPlugin; 72 graphics = pluginman.getPlugin!GraphicsPlugin; 73 clientWorld = pluginman.getPlugin!ClientWorld; 74 75 evDispatcher.subscribeToEvent(&onUpdateEvent); 76 evDispatcher.subscribeToEvent(&drawDebug); 77 } 78 79 void onUpdateEvent(ref UpdateEvent event) 80 { 81 traceCursor(); 82 drawDebugCursor(); 83 } 84 85 BlockId pickBlock() 86 { 87 return clientWorld.worldAccess.getBlock(blockPos); 88 } 89 90 void fillBox(WorldBox box, BlockId blockId) 91 { 92 connection.send(FillBlockBoxPacket(box, blockId)); 93 } 94 95 void traceCursor() 96 { 97 StopWatch sw; 98 sw.start(); 99 100 auto isBlockSolid = (ivec3 blockWorldPos) { 101 auto block = clientWorld.worldAccess.getBlock( 102 BlockWorldPos(blockWorldPos, clientWorld.currentDimention)); 103 return blockPlugin.getBlocks()[block].isVisible; 104 }; 105 106 traceBatch.reset(); 107 108 cursorHit = traceRay( 109 isBlockSolid, 110 graphics.camera.position, 111 graphics.camera.target, 112 600.0, // max distance 113 hitPosition, 114 hitNormal, 115 traceBatch); 116 117 if (cursorHit) { 118 import std.math : floor; 119 auto camPos = graphics.camera.position; 120 auto camBlock = ivec3(cast(int)floor(camPos.x), cast(int)floor(camPos.y), cast(int)floor(camPos.z)); 121 cameraInSolidBlock = BlockWorldPos(camBlock, 0) == BlockWorldPos(hitPosition, 0); 122 } else { 123 cameraInSolidBlock = false; 124 } 125 126 blockPos = BlockWorldPos(hitPosition, clientWorld.currentDimention); 127 sideBlockPos = BlockWorldPos(blockPos.xyz + hitNormal, clientWorld.currentDimention); 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 140 void drawCursor(BlockWorldPos block, Color3ub color) 141 { 142 graphics.debugBatch.putCube( 143 vec3(block.xyz) - cursorOffset, 144 cursorSize, color, false); 145 } 146 147 void drawDebug(ref RenderSolid3dEvent event) 148 { 149 //graphics.draw(hitBatch); 150 } 151 }