fix server inventory item physics bug
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit

This commit is contained in:
austin 2025-04-26 16:43:29 -04:00
parent 75fe5a9d1a
commit c8696226f0
6 changed files with 163 additions and 3 deletions

View File

@ -1548,6 +1548,7 @@ Fix fab file reading
Fab tool can show transparent, loaded version of fab file Fab tool can show transparent, loaded version of fab file
Interaction target tooltip at top of window Interaction target tooltip at top of window
Interaction target tooltip shows entity target, voxel targets Interaction target tooltip shows entity target, voxel targets
Fix bug where inventory items aren't destroying physics on server

View File

@ -306,7 +306,7 @@ public class InventoryUtils {
public static Entity clientConstructInInventoryItem(Entity parentContainer, String type){ public static Entity clientConstructInInventoryItem(Entity parentContainer, String type){
//sanity checks //sanity checks
boolean creatureIsCreature = CreatureUtils.isCreature(parentContainer); boolean creatureIsCreature = CreatureUtils.isCreature(parentContainer);
boolean hasInventory = hasNaturalInventory(parentContainer); boolean hasInventory = InventoryUtils.hasNaturalInventory(parentContainer);
if(creatureIsCreature && hasInventory){ if(creatureIsCreature && hasInventory){
//if we pass sanity checks, actually perform transform //if we pass sanity checks, actually perform transform
//get inventory //get inventory

View File

@ -7,6 +7,7 @@ import org.joml.Vector3d;
import org.ode4j.ode.DBody; import org.ode4j.ode.DBody;
import electrosphere.collision.PhysicsEntityUtils; import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.collision.PhysicsUtils;
import electrosphere.collision.collidable.Collidable; import electrosphere.collision.collidable.Collidable;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.ClientEntityUtils; import electrosphere.entity.ClientEntityUtils;
@ -417,10 +418,10 @@ public class ItemUtils {
* @param containingParent The parent that contains the item * @param containingParent The parent that contains the item
*/ */
public static Entity clientRecreateContainerItem(Entity item, Entity containingParent){ public static Entity clientRecreateContainerItem(Entity item, Entity containingParent){
if(isItem(item)){ if(ItemUtils.isItem(item)){
Item itemData = Globals.gameConfigCurrent.getItemMap().getItem(ItemUtils.getType(item)); Item itemData = Globals.gameConfigCurrent.getItemMap().getItem(ItemUtils.getType(item));
Entity rVal = EntityCreationUtils.createClientNonSpatialEntity(); Entity rVal = EntityCreationUtils.createClientNonSpatialEntity();
if(getEquipWhitelist(item) != null){ if(ItemUtils.getEquipWhitelist(item) != null){
rVal.putData(EntityDataStrings.ITEM_EQUIP_WHITELIST, getEquipWhitelist(item)); rVal.putData(EntityDataStrings.ITEM_EQUIP_WHITELIST, getEquipWhitelist(item));
} }
if(itemData.getWeaponData() != null){ if(itemData.getWeaponData() != null){
@ -493,6 +494,11 @@ public class ItemUtils {
//apply item transforms to an entity //apply item transforms to an entity
ItemUtils.serverApplyItemEntityTransforms(realm, parentPos, rVal, itemData); ItemUtils.serverApplyItemEntityTransforms(realm, parentPos, rVal, itemData);
//destroy physics
if(realm.getCollisionEngine() != null){
realm.getCollisionEngine().destroyPhysics(rVal);
}
//error checking //error checking
if(Globals.realmManager.getEntityRealm(rVal) == null){ if(Globals.realmManager.getEntityRealm(rVal) == null){
LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Created item without it being assigned to a realm!")); LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Created item without it being assigned to a realm!"));

View File

@ -136,4 +136,52 @@ public class InventoryUtilsTests extends EntityTestTemplate {
assertEquals(naturalInventory.getItems().size(),0); assertEquals(naturalInventory.getItems().size(),0);
} }
/**
* Make sure clientConstructInInventoryItem performs its intended function
*/
@IntegrationTest
public void test_clientConstructInInventoryItem(){
//warm up engine
TestEngineUtils.simulateFrames(1);
//spawn entities
TestEngineUtils.spawnPlayerEntity();
//wait for entities to propagate to client
TestEngineUtils.simulateFrames(1);
//verify the client got the extra entities
Set<Entity> clientSideCreatures = Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.CREATURE);
assertEquals(1, clientSideCreatures.size());
Set<Entity> clientSideItems = Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM);
assertEquals(0, clientSideItems.size());
//grab player entity
Entity clientCreature = clientSideCreatures.iterator().next();
Globals.playerEntity = clientCreature;
//try creating the item on the client
InventoryUtils.clientConstructInInventoryItem(clientCreature, "Katana2H");
//verify we still have everything
clientSideCreatures = Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.CREATURE);
assertEquals(1, clientSideCreatures.size());
clientSideItems = Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM);
assertEquals(1, clientSideItems.size());
//grab the item in particular
Entity child = clientSideItems.iterator().next();
//
//verify was created properly
assertTrue(ItemUtils.isItem(child));
assertTrue(ItemUtils.isWeapon(child));
assertNotNull(ItemUtils.getContainingParent(child));
//
//verify the item is stored in the inventory properly
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(clientCreature);
assertEquals(naturalInventory.getItems().size(),1);
}
} }

View File

@ -0,0 +1,82 @@
package electrosphere.entity.types.item;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Set;
import electrosphere.collision.PhysicsEntityUtils;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityTags;
import electrosphere.entity.state.inventory.InventoryUtils;
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
import electrosphere.game.data.item.Item;
import electrosphere.test.annotations.IntegrationTest;
import electrosphere.test.template.EntityTestTemplate;
import electrosphere.test.testutils.TestEngineUtils;
/**
* Integration tests for ItemUtils
*/
public class ItemUtilsTests extends EntityTestTemplate {
/**
* Make sure clientAttemptStoreItem performs its intended function
*/
@IntegrationTest
public void test_serverCreateContainerItem(){
//warm up engine
TestEngineUtils.simulateFrames(1);
//spawn entities
TestEngineUtils.spawnPlayerEntity();
//wait for entities to propagate to client
TestEngineUtils.simulateFrames(1);
//verify the client got the extra entities
Set<Entity> clientSideCreatures = Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.CREATURE);
assertEquals(1, clientSideCreatures.size());
Set<Entity> clientSideItems = Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM);
assertEquals(0, clientSideItems.size());
//get server equivalent of client entity
Entity serverEquivalent = TestEngineUtils.getServerEquivalent(clientSideCreatures.iterator().next());
//grab player entity
Entity clientCreature = clientSideCreatures.iterator().next();
Globals.playerEntity = clientCreature;
//attempt to store
Item item = Globals.gameConfigCurrent.getItemMap().getItem("Katana2H");
ItemUtils.serverCreateContainerItem(serverEquivalent, item);
//propagate to client
TestEngineUtils.simulateFrames(2);
//verify we still have everything
clientSideCreatures = Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.CREATURE);
assertEquals(1, clientSideCreatures.size());
clientSideItems = Globals.clientSceneWrapper.getScene().getEntitiesWithTag(EntityTags.ITEM);
assertEquals(1, clientSideItems.size());
//grab the item in particular
Entity child = clientSideItems.iterator().next();
//
//verify was created properly
assertTrue(ItemUtils.isItem(child));
assertTrue(ItemUtils.isWeapon(child));
assertNotNull(ItemUtils.getContainingParent(child));
assertNull(PhysicsEntityUtils.getCollidable(child));
//
//verify the item is stored in the inventory properly
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(clientCreature);
assertEquals(naturalInventory.getItems().size(),1);
}
}

View File

@ -14,7 +14,9 @@ import electrosphere.engine.loadingthreads.LoadingThread;
import electrosphere.entity.Entity; import electrosphere.entity.Entity;
import electrosphere.entity.types.creature.CreatureTemplate; import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.net.server.ServerConnectionHandler; import electrosphere.net.server.ServerConnectionHandler;
import electrosphere.net.server.protocol.CharacterProtocol;
import electrosphere.server.character.PlayerCharacterCreation; import electrosphere.server.character.PlayerCharacterCreation;
import electrosphere.server.datacell.utils.EntityLookupUtils;
/** /**
* Utils for testing the engine * Utils for testing the engine
@ -69,6 +71,26 @@ public class TestEngineUtils {
return null; return null;
} }
/**
* Gets the server equivalent of an entity
* @param clientEntity The client entity
* @return The server entity
*/
public static Entity getServerEquivalent(Entity clientEntity){
if(clientEntity == null){
fail("Provided null entity to get server equivalent!");
}
if(Globals.clientSceneWrapper.containsServerId(clientEntity.getId())){
fail("Provided server entity to getServerEquivalent");
}
int serverId = Globals.clientSceneWrapper.mapClientToServerId(clientEntity.getId());
Entity rVal = EntityLookupUtils.getEntityById(serverId);
if(rVal == null){
fail("Failed to find client entity at server id lookup for id: " + clientEntity.getId());
}
return rVal;
}
/** /**
* Waits for a given test to be true * Waits for a given test to be true
* @param test The test to wait for * @param test The test to wait for
@ -142,6 +164,7 @@ public class TestEngineUtils {
CreatureTemplate creatureTemplate = CreatureTemplate.createDefault("human"); CreatureTemplate creatureTemplate = CreatureTemplate.createDefault("human");
ServerConnectionHandler serverConnection = Globals.server.getFirstConnection(); ServerConnectionHandler serverConnection = Globals.server.getFirstConnection();
serverConnection.setCreatureTemplate(creatureTemplate); serverConnection.setCreatureTemplate(creatureTemplate);
serverConnection.setCharacterId(CharacterProtocol.SPAWN_EXISTING_TEMPLATE);
PlayerCharacterCreation.spawnPlayerCharacter(serverConnection); PlayerCharacterCreation.spawnPlayerCharacter(serverConnection);
} }