From d6b30dd3a5df4b84a287305f807442064f4cf68d Mon Sep 17 00:00:00 2001 From: Kahrl Date: Tue, 29 Nov 2011 17:15:18 +0200 Subject: CraftItem rework and Lua interface --- src/game.cpp | 564 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 306 insertions(+), 258 deletions(-) (limited to 'src/game.cpp') diff --git a/src/game.cpp b/src/game.cpp index 5bbd92d55..abeceae0b 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "profiler.h" #include "mainmenumanager.h" +#include "craftitemdef.h" #include "gettext.h" #include "log.h" #include "filesys.h" @@ -87,8 +88,6 @@ Queue inventory_action_queue; // This is a copy of the inventory that the client's environment has Inventory local_inventory; -u16 g_selected_item = 0; - /* Text input system */ @@ -159,7 +158,7 @@ private: void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font, ITextureSource *tsrc, v2s32 centerlowerpos, s32 imgsize, s32 itemcount, - Inventory *inventory, s32 halfheartcount) + Inventory *inventory, s32 halfheartcount, u16 playeritem) { InventoryList *mainlist = inventory->getList("main"); if(mainlist == NULL) @@ -190,7 +189,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font, core::rect rect = imgrect + pos + v2s32(padding+i*(imgsize+padding*2), padding); - if(g_selected_item == i) + if(playeritem == i) { video::SColor c_outside(255,255,0,0); //video::SColor c_outside(255,0,0,0); @@ -288,16 +287,65 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font, } } +/* + Check if a node is pointable +*/ +inline bool isPointableNode(const MapNode& n, + Client *client, bool liquids_pointable) +{ + const ContentFeatures &features = client->getNodeDefManager()->get(n); + return features.pointable || + (liquids_pointable && features.isLiquid()); +} + /* Find what the player is pointing at */ -void getPointedNode(Client *client, v3f player_position, +PointedThing getPointedThing(Client *client, v3f player_position, v3f camera_direction, v3f camera_position, - bool &nodefound, core::line3d shootline, - v3s16 &nodepos, v3s16 &neighbourpos, - core::aabbox3d &nodehilightbox, - f32 d) + core::line3d shootline, f32 d, + bool liquids_pointable, + bool look_for_object, + core::aabbox3d &hilightbox, + bool &should_show_hilightbox, + ClientActiveObject *&selected_object) { + PointedThing result; + + hilightbox = core::aabbox3d(0,0,0,0,0,0); + should_show_hilightbox = false; + selected_object = NULL; + + // First try to find a pointed at active object + if(look_for_object) + { + selected_object = client->getSelectedActiveObject(d*BS, + camera_position, shootline); + } + if(selected_object != NULL) + { + core::aabbox3d *selection_box + = selected_object->getSelectionBox(); + // Box should exist because object was returned in the + // first place + assert(selection_box); + + v3f pos = selected_object->getPosition(); + + hilightbox = core::aabbox3d( + selection_box->MinEdge + pos, + selection_box->MaxEdge + pos + ); + + should_show_hilightbox = selected_object->doShowSelectionBox(); + + result.type = POINTEDTHING_OBJECT; + result.object_id = selected_object->getId(); + return result; + } + + // That didn't work, try to find a pointed at node + f32 mindistance = BS * 1001; v3s16 pos_i = floatToInt(player_position, BS); @@ -321,13 +369,13 @@ void getPointedNode(Client *client, v3f player_position, try { n = client->getNode(v3s16(x,y,z)); - if(client->getNodeDefManager()->get(n).pointable == false) - continue; } catch(InvalidPositionException &e) { continue; } + if(!isPointableNode(n, client, liquids_pointable)) + continue; v3s16 np(x,y,z); v3f npf = intToFloat(np, BS); @@ -402,11 +450,12 @@ void getPointedNode(Client *client, v3f player_position, continue; if(!faceboxes[i].intersectsWithLine(shootline)) continue; - nodefound = true; - nodepos = np; - neighbourpos = np+facedirs[i]; + result.type = POINTEDTHING_NODE; + result.node_undersurface = np; + result.node_abovesurface = np+facedirs[i]; mindistance = distance; - nodehilightbox = box; + hilightbox = box; + should_show_hilightbox = true; } } else if(f.selection_box.type == NODEBOX_WALLMOUNTED) @@ -458,11 +507,12 @@ void getPointedNode(Client *client, v3f player_position, { if(box.intersectsWithLine(shootline)) { - nodefound = true; - nodepos = np; - neighbourpos = np; + result.type = POINTEDTHING_NODE; + result.node_undersurface = np; + result.node_abovesurface = np; mindistance = distance; - nodehilightbox = box; + hilightbox = box; + should_show_hilightbox = true; } } } @@ -498,25 +548,28 @@ void getPointedNode(Client *client, v3f player_position, if(facebox.intersectsWithLine(shootline)) { - nodefound = true; - nodepos = np; - neighbourpos = np + dirs[i]; + result.type = POINTEDTHING_NODE; + result.node_undersurface = np; + result.node_abovesurface = np + dirs[i]; mindistance = distance; - //nodehilightbox = facebox; + //hilightbox = facebox; const float d = 0.502; core::aabbox3d nodebox (-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d); - v3f nodepos_f = intToFloat(nodepos, BS); + v3f nodepos_f = intToFloat(np, BS); nodebox.MinEdge += nodepos_f; nodebox.MaxEdge += nodepos_f; - nodehilightbox = nodebox; + hilightbox = nodebox; + should_show_hilightbox = true; } } // if distance < mindistance } // for dirs } // regular block } // for coords + + return result; } void update_skybox(video::IVideoDriver* driver, ITextureSource *tsrc, @@ -642,6 +695,8 @@ void the_game( IWritableToolDefManager *tooldef = createToolDefManager(); // Create node definition manager IWritableNodeDefManager *nodedef = createNodeDefManager(); + // Create CraftItem definition manager + IWritableCraftItemDefManager *craftitemdef = createCraftItemDefManager(); // Add chat log output for errors to be shown in chat LogOutputBuffer chat_log_error_buf(LMT_ERROR); @@ -670,7 +725,7 @@ void the_game( MapDrawControl draw_control; Client client(device, playername.c_str(), password, draw_control, - tsrc, tooldef, nodedef); + tsrc, tooldef, nodedef, craftitemdef); // Client acts as our GameDef IGameDef *gamedef = &client; @@ -781,7 +836,8 @@ void the_game( // End condition if(client.texturesReceived() && client.tooldefReceived() && - client.nodedefReceived()){ + client.nodedefReceived() && + client.craftitemdefReceived()){ got_content = true; break; } @@ -801,6 +857,8 @@ void the_game( ss< frametime_log; - float nodig_delay_counter = 0.0; + float nodig_delay_timer = 0.0; float dig_time = 0.0; u16 dig_index = 0; - v3s16 nodepos_old(-32768,-32768,-32768); + PointedThing pointed_old; + bool digging = false; bool ldown_for_dig = false; float damage_flash_timer = 0; @@ -1083,7 +1142,10 @@ void the_game( /* Run timers */ - object_hit_delay_timer -= dtime; + if(nodig_delay_timer >= 0) + nodig_delay_timer -= dtime; + if(object_hit_delay_timer >= 0) + object_hit_delay_timer -= dtime; g_profiler->add("Elapsed time", dtime); g_profiler->avg("FPS", 1./dtime); @@ -1228,7 +1290,7 @@ void the_game( a->count = 0; a->from_inv = "current_player"; a->from_list = "main"; - a->from_i = g_selected_item; + a->from_i = client.getPlayerItem(); client.inventoryAction(a); } else if(input->wasKeyDown(getKeySetting("keymap_inventory"))) @@ -1369,6 +1431,7 @@ void the_game( } // Item selection with mouse wheel + u16 new_playeritem = client.getPlayerItem(); { s32 wheel = input->getMouseWheel(); u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE-1, @@ -1376,17 +1439,17 @@ void the_game( if(wheel < 0) { - if(g_selected_item < max_item) - g_selected_item++; + if(new_playeritem < max_item) + new_playeritem++; else - g_selected_item = 0; + new_playeritem = 0; } else if(wheel > 0) { - if(g_selected_item > 0) - g_selected_item--; + if(new_playeritem > 0) + new_playeritem--; else - g_selected_item = max_item; + new_playeritem = max_item; } } @@ -1398,10 +1461,10 @@ void the_game( { if(i < PLAYER_INVENTORY_SIZE && i < hotbar_itemcount) { - g_selected_item = i; + new_playeritem = i; infostream<<"Selected item: " - <getItem(client.getPlayerItem()); + if(item) + { + if((std::string)item->getName() == "ToolItem") + { + ToolItem *titem = (ToolItem*)item; + playeritem_toolname = titem->getToolName(); + } + + playeritem_usable = item->isUsable(); + + playeritem_liquids_pointable = + item->areLiquidsPointable(); + } + } + } + /* Calculate what block is the crosshair pointing to */ //u32 t1 = device->getTimer()->getRealTime(); - //f32 d = 4; // max. distance f32 d = 4; // max. distance core::line3d shootline(camera_position, camera_position + camera_direction * BS * (d+1)); - ClientActiveObject *selected_active_object - = client.getSelectedActiveObject - (d*BS, camera_position, shootline); - - bool left_punch = false; - bool left_punch_muted = false; - - if(selected_active_object != NULL && !ldown_for_dig) - { - /* Clear possible cracking animation */ - if(nodepos_old != v3s16(-32768,-32768,-32768)) - { - client.clearTempMod(nodepos_old); - dig_time = 0.0; - nodepos_old = v3s16(-32768,-32768,-32768); - } - - //infostream<<"Client returned selected_active_object != NULL"< *selection_box - = selected_active_object->getSelectionBox(); - // Box should exist because object was returned in the - // first place - assert(selection_box); + core::aabbox3d hilightbox; + bool should_show_hilightbox = false; + ClientActiveObject *selected_object = NULL; - v3f pos = selected_active_object->getPosition(); + PointedThing pointed = getPointedThing( + // input + &client, player_position, camera_direction, + camera_position, shootline, d, + playeritem_liquids_pointable, !ldown_for_dig, + // output + hilightbox, should_show_hilightbox, + selected_object); - core::aabbox3d box_on_map( - selection_box->MinEdge + pos, - selection_box->MaxEdge + pos - ); - - if(selected_active_object->doShowSelectionBox()) - hilightboxes.push_back(box_on_map); + if(pointed != pointed_old) + { + infostream<<"Pointing at "<infoText()); + /* + Visualize selection + */ + if(should_show_hilightbox) + hilightboxes.push_back(hilightbox); - //if(input->getLeftClicked()) - if(input->getLeftState()) + /* + Stop digging when + - releasing left mouse button + - pointing away from node + */ + if(digging) + { + if(input->getLeftReleased()) { - bool do_punch = false; - bool do_punch_damage = false; - if(object_hit_delay_timer <= 0.0){ - do_punch = true; - do_punch_damage = true; - object_hit_delay_timer = object_hit_delay; - } - if(input->getLeftClicked()){ - do_punch = true; - } - if(do_punch){ - infostream<<"Left-clicked object"<getId(), g_selected_item); + else + { + infostream<<"Pointing away from node" + <<" (stopped digging)"<getRightClicked()) + if(!digging) { - infostream<<"Right-clicked object"<getId(), g_selected_item); + client.interact(1, pointed_old); + client.clearTempMod(pointed_old.node_undersurface); + dig_time = 0.0; } } - else // selected_object == NULL + if(!digging && ldown_for_dig && !input->getLeftState()) { + ldown_for_dig = false; + } - /* - Find out which node we are pointing at - */ - - bool nodefound = false; - v3s16 nodepos; - v3s16 neighbourpos; - core::aabbox3d nodehilightbox; - - getPointedNode(&client, player_position, - camera_direction, camera_position, - nodefound, shootline, - nodepos, neighbourpos, - nodehilightbox, d); - - if(!nodefound){ - if(nodepos_old != v3s16(-32768,-32768,-32768)) - { - client.clearTempMod(nodepos_old); - dig_time = 0.0; - nodepos_old = v3s16(-32768,-32768,-32768); - ldown_for_dig = false; - } - } else { - /* - Visualize selection - */ + bool left_punch = false; + bool left_punch_muted = false; - hilightboxes.push_back(nodehilightbox); + if(playeritem_usable && input->getLeftState()) + { + if(input->getLeftClicked()) + client.interact(4, pointed); + } + else if(pointed.type == POINTEDTHING_NODE) + { + v3s16 nodepos = pointed.node_undersurface; + v3s16 neighbourpos = pointed.node_abovesurface; /* Check information text of node @@ -1744,139 +1815,94 @@ void the_game( infotext = narrow_to_wide(meta->infoText()); } - //MapNode node = client.getNode(nodepos); - /* Handle digging */ - if(input->getLeftReleased()) - { - client.clearTempMod(nodepos); - dig_time = 0.0; - ldown_for_dig = false; - } - if(nodig_delay_counter > 0.0) + if(nodig_delay_timer <= 0.0 && input->getLeftState()) { - nodig_delay_counter -= dtime; - } - else - { - if(nodepos != nodepos_old) + if(!digging) { - infostream<<"Pointing at ("<getDiggingProperties(playeritem_toolname); + DiggingProperties prop = + getDiggingProperties(material, &tp, nodedef); + + float dig_time_complete = 0.0; + + if(prop.diggable == false) + { + /*infostream<<"Material "<<(int)material + <<" not diggable with \"" + <getLeftClicked() || - (input->getLeftState() && nodepos != nodepos_old)) + if(dig_time_complete >= 0.001) { - infostream<<"Started digging"<getLeftClicked()) + // This is for torches + else { - client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0)); - ldown_for_dig = true; + dig_index = CRACK_ANIMATION_LENGTH; } - if(input->getLeftState()) + + if(dig_index < CRACK_ANIMATION_LENGTH) { - MapNode n = client.getNode(nodepos); - - // Get tool name. Default is "" = bare hands - std::string toolname = ""; - InventoryList *mlist = local_inventory.getList("main"); - if(mlist != NULL) - { - InventoryItem *item = mlist->getItem(g_selected_item); - if(item && (std::string)item->getName() == "ToolItem") - { - ToolItem *titem = (ToolItem*)item; - toolname = titem->getToolName(); - } - } + //TimeTaker timer("client.setTempMod"); + //infostream<<"dig_index="<getDiggingProperties(toolname); - DiggingProperties prop = - getDiggingProperties(material, &tp, nodedef); - - float dig_time_complete = 0.0; + dig_time = 0; + digging = false; - if(prop.diggable == false) - { - /*infostream<<"Material "<<(int)material - <<" not diggable with \"" - <= 0.001) - { - dig_index = (u16)((float)CRACK_ANIMATION_LENGTH - * dig_time/dig_time_complete); - } - // This is for torches - else - { - dig_index = CRACK_ANIMATION_LENGTH; - } + nodig_delay_timer = dig_time_complete + / (float)CRACK_ANIMATION_LENGTH; - if(dig_index < CRACK_ANIMATION_LENGTH) + // We don't want a corresponding delay to + // very time consuming nodes + if(nodig_delay_timer > 0.5) { - //TimeTaker timer("client.setTempMod"); - //infostream<<"dig_index="< 0.5) - { - nodig_delay_counter = 0.5; - } - // We want a slight delay to very little - // time consuming nodes - float mindelay = 0.15; - if(nodig_delay_counter < mindelay) - { - nodig_delay_counter = mindelay; - } + nodig_delay_timer = mindelay; } + } - dig_time += dtime; + dig_time += dtime; - camera.setDigging(0); // left click animation - } + camera.setDigging(0); // left click animation } - - + if(input->getRightClicked()) { infostream<<"Ground right-clicked"<infoText()); + + //if(input->getLeftClicked()) + if(input->getLeftState()) + { + bool do_punch = false; + bool do_punch_damage = false; + if(object_hit_delay_timer <= 0.0){ + do_punch = true; + do_punch_damage = true; + object_hit_delay_timer = object_hit_delay; + } + if(input->getLeftClicked()){ + do_punch = true; + } + if(do_punch){ + infostream<<"Left-clicked object"<getPosition(); + v3f dir = (objpos - player_position).normalize(); + + bool disable_send = selected_object->directReportPunch(playeritem_toolname, dir); + if(!disable_send) + client.interact(0, pointed); + } + } + else if(input->getRightClicked()) + { + infostream<<"Right-clicked object"<getLeftClicked() && !left_punch_muted)) { @@ -1950,20 +2011,7 @@ void the_game( input->resetLeftClicked(); input->resetRightClicked(); - - if(input->getLeftReleased()) - { - infostream<<"Left button released (stopped digging)" - <getRightReleased()) - { - //inostream<resetLeftReleased(); input->resetRightReleased(); @@ -2210,12 +2258,12 @@ void the_game( Inventory */ - static u16 old_selected_item = 65535; - if(client.getLocalInventoryUpdated() - || g_selected_item != old_selected_item) + if(client.getPlayerItem() != new_playeritem) + { + client.selectPlayerItem(new_playeritem); + } + if(client.getLocalInventoryUpdated()) { - client.selectPlayerItem(g_selected_item); - old_selected_item = g_selected_item; //infostream<<"Updating local inventory"<getItem(g_selected_item); + item = mlist->getItem(client.getPlayerItem()); camera.wield(item, gamedef); } @@ -2350,7 +2398,7 @@ void the_game( draw_hotbar(driver, font, tsrc, v2s32(displaycenter.X, screensize.Y), hotbar_imagesize, hotbar_itemcount, &local_inventory, - client.getHP()); + client.getHP(), client.getPlayerItem()); } /* -- cgit v1.2.3