I try to fix an abandoned plugin, which works to nearly 70%. But it has some critical problems and I solved some issues, but one big is open.
It's the Rust plugin "stats" and it captures which structures get build or destroyed. If anyone is raiding someone, I can see who, when, what and on which coordinates has destroyed a wall.
So this work:
- wall, foundation, pillar, floor, u shaped stairs, floor triangle, window, doorway, steps, and so on
This doesn't work since Facepunch reorganized the whole prefab story. Since then it can't track things like:
sign.small.wood.prefab
barricate.concrete.prefab
door.hinged.metal.prefab
Thats no building stuff, that are deployables. I think thats the problem. But on the other side, how can I track all there stuff with the "placements" menu?
Here is some C# stuff:
Thats the stuff which tracks the whole placement components. It work with "component" things...
This is the part which look if a building, an animal or player get "destroyed"Code:void OnEntityBuilt(Planner planner, GameObject component) { Vector3 pos = planner.ownerPlayer.GetEstimatedWorldPosition(); string name = component.ToBaseEntity().LookupShortPrefabName(); if(component.ToBaseEntity() is BuildingBlock) { name = ((BuildingBlock)component.ToBaseEntity()).blockDefinition.info.name.english; } executeQuery("INSERT INTO player_place_building (player, building, pos_x, pos_y, pos_z, date) VALUES (?, ?, ?, ?, ?, ?)", planner.ownerPlayer.userID, name, pos.x, pos.y, pos.z, getTime()); }
I think I must rewrite some stuff here and can't track OnEntityDeath with this 3 cases. The building part must be ripped off and get it's own querry where I can check for components?Code:void OnEntityDeath(BaseCombatEntity entity, HitInfo hitInfo) { if(entity.lastAttacker != null && entity.lastAttacker is BasePlayer) { Vector3 pos = entity.lastAttacker.GetEstimatedWorldPosition(); if(entity is BuildingBlock) { executeQuery("INSERT INTO player_destroy_building (player, building, pos_x, pos_y, pos_z, date) VALUES (?, ?, ?, ?, ?, ?)", ((BasePlayer)entity.lastAttacker).userID, ((BuildingBlock)entity).blockDefinition.info.name.english, pos.x, pos.y, pos.z, getTime()); } else if(entity is BaseNPC) { executeQuery("INSERT INTO player_animal_kill (player, animal, pos_x, pos_y, pos_z, date) VALUES (?, ?, ?, ?, ?, ?)", ((BasePlayer)entity.lastAttacker).userID, UppercaseFirst(entity.LookupShortPrefabName()), pos.x, pos.y, pos.z, getTime()); } else if(entity is BasePlayer && entity != entity.lastAttacker) { executeQuery("INSERT INTO player_kill (killer, victim, pos_x, pos_y, pos_z, weapon, date) VALUES (?, ?, ?, ?, ?, ?, ?)", ((BasePlayer)entity.lastAttacker).userID, ((BasePlayer)entity).userID, pos.x, pos.y, pos.z, ((BasePlayer)entity.lastAttacker).GetActiveItem().info.displayName.english, getTime()); } } if(entity is BasePlayer) { Vector3 pos = entity.GetEstimatedWorldPosition(); string cause = entity.lastDamage.ToString(); executeQuery("INSERT INTO player_death (player, cause, pos_x, pos_y, pos_z, date) VALUES (?, ?, ?, ?, ?, ?)", ((BasePlayer)entity).userID, cause, pos.x, pos.y, pos.z, getTime()); } }
I have nearly zero experience in oxide api or coding stuff. Some little fixes are okay, but here I get mad. I tried some things like change the querry so it checks for components, but OnEntityDeath has no components like OnEntityBuild or I'm to dump to understand.
Please help me and thank you for reading
Nathaira
Can't track destroyed buildings with .prefab but walls, foundations work
Discussion in 'Rust Development' started by Nathaira, Jun 24, 2016.
-
Just some update.
I and a friend of me tested a lot of stuff and we didn't know if and how we can check if an entity like a door or campfire get destroyed used by the hook OnEntityDeath. Some people in other threads in this board used this hook for tracking if a storage box or a tool cupboard is destroyed. So it is possible?
Maybe it's better for debugging that I did not sent it directly as SQL querry, but to the console as oxide notification. How can I do that?
Thanks NathiLast edited by a moderator: Jun 25, 2016 -
Code:
void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) { if (entity is BuildingBlock || entity is SimpleBuildingBlock || entity is StabilityEntity || entity is Door || entity is StorageContainer || entity is SleepingBag || entity is BaseOven || entity is AutoTurret || entity is BuildingPrivlidge || entity is Signage || entity is Barricade || entity is BaseResourceExtractor) { ... } } void OnEntityDeath(BaseCombatEntity entity, HitInfo info) { if (entity is BuildingBlock || entity is SimpleBuildingBlock || entity is StabilityEntity || entity is Door || entity is StorageContainer || entity is SleepingBag || entity is BaseOven || entity is AutoTurret || entity is BuildingPrivlidge || entity is Signage || entity is Barricade || entity is BaseResourceExtractor) { ... } }
you check for each type directly if it matches the type...this should help you to find a solution to detect doors and so on.
-
Hey Fuji
Thanks for your help and post. I blast some sleeping bag, storage box, campfire, door and wood window and got this:
Code:(10:51:18) | [Oxide] 10:51 [Error] Failed to call hook 'OnEntityDeath' on plugin 'stats v1.5.2' (InvalidCastException: Cannot cast from source type to destination type.) (10:51:18) | [Oxide] 10:51 [Debug] at Oxide.Plugins.Stats.OnEntityDeath (.BaseCombatEntity entity, .HitInfo hitInfo) [0x00000] in <filename unknown>:0 at Oxide.Plugins.Stats.DirectCallHook (System.String name, System.Object& ret, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Plugins.CSharpPlugin.InvokeMethod (HookMethod method, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Core.Plugins.CSPlugin.OnCallHook (System.String name, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Core.Plugins.Plugin.CallHook (System.String name, System.Object[] args) [0x00000] in <filename unknown>:0 (10:51:19) | [Oxide] 10:51 [Warning] Calling 'OnEntityDeath' on 'stats v1.5.2' took 503ms (10:51:19) | [Oxide] 10:51 [Error] Failed to call hook 'OnEntityDeath' on plugin 'stats v1.5.2' (InvalidCastException: Cannot cast from source type to destination type.) (10:51:20) | [Oxide] 10:51 [Debug] at Oxide.Plugins.Stats.OnEntityDeath (.BaseCombatEntity entity, .HitInfo hitInfo) [0x00000] in <filename unknown>:0 at Oxide.Plugins.Stats.DirectCallHook (System.String name, System.Object& ret, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Plugins.CSharpPlugin.InvokeMethod (HookMethod method, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Core.Plugins.CSPlugin.OnCallHook (System.String name, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Core.Plugins.Plugin.CallHook (System.String name, System.Object[] args) [0x00000] in <filename unknown>:0 (10:51:20) | [Oxide] 10:51 [Warning] Calling 'OnEntityDeath' on 'stats v1.5.2' took 714ms (10:51:22) | [Oxide] 10:51 [Error] Failed to call hook 'OnEntityDeath' on plugin 'stats v1.5.2' (InvalidCastException: Cannot cast from source type to destination type.) (10:51:22) | [Oxide] 10:51 [Debug] at Oxide.Plugins.Stats.OnEntityDeath (.BaseCombatEntity entity, .HitInfo hitInfo) [0x00000] in <filename unknown>:0 at Oxide.Plugins.Stats.DirectCallHook (System.String name, System.Object& ret, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Plugins.CSharpPlugin.InvokeMethod (HookMethod method, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Core.Plugins.CSPlugin.OnCallHook (System.String name, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Core.Plugins.Plugin.CallHook (System.String name, System.Object[] args) [0x00000] in <filename unknown>:0 (10:51:23) | [Oxide] 10:51 [Warning] Calling 'OnEntityDeath' on 'stats v1.5.2' took 504ms (10:51:35) | [Oxide] 10:52 [Error] Failed to call hook 'OnEntityDeath' on plugin 'stats v1.5.2' (InvalidCastException: Cannot cast from source type to destination type.) (10:51:35) | [Oxide] 10:52 [Debug] at Oxide.Plugins.Stats.OnEntityDeath (.BaseCombatEntity entity, .HitInfo hitInfo) [0x00000] in <filename unknown>:0 at Oxide.Plugins.Stats.DirectCallHook (System.String name, System.Object& ret, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Plugins.CSharpPlugin.InvokeMethod (HookMethod method, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Core.Plugins.CSPlugin.OnCallHook (System.String name, System.Object[] args) [0x00000] in <filename unknown>:0 at Oxide.Core.Plugins.Plugin.CallHook (System.String name, System.Object[] args) [0x00000] in <filename unknown>:0 (10:51:36) | [Oxide] 10:52 [Warning] Calling 'OnEntityDeath' on 'stats v1.5.2' took 590ms
Code:void OnEntityDeath(BaseCombatEntity entity, HitInfo hitInfo) { if(entity.lastAttacker != null && entity.lastAttacker is BasePlayer) { Vector3 pos = entity.lastAttacker.GetEstimatedWorldPosition(); if(entity is BuildingBlock || entity is SimpleBuildingBlock || entity is StabilityEntity || entity is Door || entity is StorageContainer || entity is SleepingBag || entity is BaseOven || entity is AutoTurret || entity is BuildingPrivlidge || entity is Signage || entity is Barricade || entity is BaseResourceExtractor) { executeQuery("INSERT INTO player_destroy_building (player, building, pos_x, pos_y, pos_z, date) VALUES (?, ?, ?, ?, ?, ?)", ((BasePlayer)entity.lastAttacker).userID, ((BuildingBlock)entity).blockDefinition.info.name.english, pos.x, pos.y, pos.z, getTime()); } else if(entity is BaseNPC) { executeQuery("INSERT INTO player_animal_kill (player, animal, pos_x, pos_y, pos_z, date) VALUES (?, ?, ?, ?, ?, ?)", ((BasePlayer)entity.lastAttacker).userID, UppercaseFirst(entity.LookupShortPrefabName()), pos.x, pos.y, pos.z, getTime()); } else if(entity is BasePlayer && entity != entity.lastAttacker) { executeQuery("INSERT INTO player_kill (killer, victim, pos_x, pos_y, pos_z, weapon, date) VALUES (?, ?, ?, ?, ?, ?, ?)", ((BasePlayer)entity.lastAttacker).userID, ((BasePlayer)entity).userID, pos.x, pos.y, pos.z, ((BasePlayer)entity.lastAttacker).GetActiveItem().info.displayName.english, getTime()); } } if(entity is BasePlayer) { Vector3 pos = entity.GetEstimatedWorldPosition(); string cause = entity.lastDamage.ToString(); executeQuery("INSERT INTO player_death (player, cause, pos_x, pos_y, pos_z, date) VALUES (?, ?, ?, ?, ?, ?)", ((BasePlayer)entity).userID, cause, pos.x, pos.y, pos.z, getTime()); } }
-
Try it instead of "((BasePlayer)entity.lastAttacker).userID" with "(entity.lastAttacker as BasePlayer).userID".
in one Line you have only "((BasePlayer)entity).userID", which would then be "(entity as BasePlayer).userID", but i would mean, there's the "lastAtttacker "missing too, or? -
I tested the new idea, but it's the same exception error. It seams that the output of the whole entity is this-and-that is some wired for the plugin?
The last if with player_death can't be lastAttacker, because that thing tracks why a player died (by animal, illness, fall damage, and so on). So no player interaction is the cause. That will be tracked by player_kill, shot by this-and-that, that means pvp action. -
You should then check, which one is generating "InvalidCastException: Cannot cast from source type to destination type." This means, you try to convert any type to another with a not supported/ not inbuilt conversion.
-
Sorry but that's the point where I've no idea what you mean. How can I do that?
-
Are you alrady familiar with NET assembly browsers and decompilers?
Like Ilspy?
ILSpy
This would be needed to explain it on this example to give you the knowledge to find alone what you need for an idea -
Not really, I've no idea of what kind of stuff you are talking ^^'' sorry but I never wrote a plugin or ripped it off and changed some things. I fixed obsolete hooks and deleted unnecessary code, but that's all. I think my problem is for the moment unsolveable, because I've no idea and it's for over 7 months unmaintained on oxide, which means the plugin is dead. :/
-
EDIT: found it > Stats, Top and Rewards for Rust | Oxide
Looks like a lot of work and prerequisites
Is'nt something like Rank-ME not capable enough for your needs?Last edited by a moderator: Jun 26, 2016 -
No it's so much older... it's this one: Stats [Unmaintained] | Oxide
At one of the last pages is the latest version, the modified version of me where I fixed the hooks. -
Perhaps you should start Request for someone who is interested to take this over?
-
Yes maybe...
With the new update series some core network things had changed.
Can someone help me?
Code:(18:52:56) | [Oxide] 18:52 [Error] stats plugin failed to compile! (18:52:56) | [Oxide] 18:52 [Error] stats.cs(484,30): error CS1061: Type `BaseNetworkable' does not contain a definition for `LookupShortPrefabName' and no extension method `LookupShortPrefabName' of type `BaseNetworkable' could be found. Are you missing an assembly reference?
Code:public EntityCount() { foreach(BaseNetworkable e in BaseNetworkable.serverEntities.All()) { if(e is BaseNPC) { switch(((BaseNPC)e).LookupShortPrefabName()) { case "horse.prefab": horses++; break; case "bear.prefab": bears++; break; case "wolf.prefab": wolves++; break; case "chicken.prefab": chickens++; break; case "boar.prefab": boars++; break; case "stag.prefab": stags++; break; } } else if(e is BaseResource) { switch(((BaseResource)e).LookupShortPrefabName()) { case "stone-ore.prefab": stone_ore++; break; case "sulfur-ore.prefab": sulfur_ore++; break; case "metal-ore.prefab": metal_ore++; break; } } else if(e is TreeEntity) { trees++; } else if(e is PlantEntity) { switch(e.LookupShortPrefabName()) { case "pumpkin.entity.prefab": pumpkins++; break; case "corn.entity.prefab": corn++; break; } } else if(e is CollectibleEntity) { switch(e.LookupShortPrefabName()) { case "stone-1.prefab": groundStone++; break; case "metalore-2.prefab": groundMetal++; break; case "sulfurore-3.prefab": groundSulfur++; break; case "hemp.prefab": groundHemp++; break; case "wood.prefab": groundWood++; break; case "mushroom-cluster-1.prefab": case "mushroom-cluster-2.prefab": case "mushroom-cluster-3.prefab": case "mushroom-cluster-4.prefab": case "mushroom-cluster-5.prefab": case "mushroom-cluster-6.prefab": groundMushroom++; break; } } } }
-
Wulf Community Admin
-
Thank you so much, but there is more broken, it'll not compile.
Code:(21:19:56) | [Oxide] 21:19 [Error] stats plugin failed to compile! (21:19:56) | [Oxide] 21:19 [Error] stats.cs(391,143): error CS1061: Type `Planner' does not contain a definition for `ownerPlayer' and no extension method `ownerPlayer' of type `Planner' could be found. Are you missing an assembly reference? void OnEntityBuilt(Planner planner, GameObject component) { Vector3 pos = planner.ownerPlayer.GetEstimatedWorldPosition(); string name = component.ToBaseEntity().ShortPrefabName; if(component.ToBaseEntity() is BuildingBlock) { name = ((BuildingBlock)component.ToBaseEntity()).blockDefinition.info.name.english; } executeQuery("INSERT INTO player_place_building (player, building, pos_x, pos_y, pos_z, date) VALUES (?, ?, ?, ?, ?, ?)", planner.ownerPlayer.userID, name, pos.x, pos.y, pos.z, getTime()); }
-
Wulf Community Admin
-
You're my hero :3
Thank you Wulf