Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
CreatureChat
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Jobs
Commits
Open sidebar
Public
CreatureChat
Commits
7bfd61e4
Commit
7bfd61e4
authored
Apr 06, 2024
by
Jonathan Thomas
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate all Entity classes to MobEntity for consistency
parent
d8d4e234
Pipeline
#11948
passed with stage
in 20 seconds
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
42 additions
and
39 deletions
+42
-39
ClickHandler.java
src/client/java/com/owlmaddie/ClickHandler.java
+8
-8
ClientEntityFinder.java
src/client/java/com/owlmaddie/ClientEntityFinder.java
+6
-4
ClientInit.java
src/client/java/com/owlmaddie/ClientInit.java
+8
-8
ChatDataManager.java
src/main/java/com/owlmaddie/ChatDataManager.java
+2
-3
ModInit.java
src/main/java/com/owlmaddie/ModInit.java
+13
-13
ServerEntityFinder.java
src/main/java/com/owlmaddie/ServerEntityFinder.java
+5
-3
No files found.
src/client/java/com/owlmaddie/ClickHandler.java
View file @
7bfd61e4
...
@@ -9,7 +9,7 @@ import net.minecraft.client.network.ClientPlayerEntity;
...
@@ -9,7 +9,7 @@ import net.minecraft.client.network.ClientPlayerEntity;
import
net.minecraft.client.render.Camera
;
import
net.minecraft.client.render.Camera
;
import
net.minecraft.entity.Entity
;
import
net.minecraft.entity.Entity
;
import
net.minecraft.entity.EntityType
;
import
net.minecraft.entity.EntityType
;
import
net.minecraft.entity.
Living
Entity
;
import
net.minecraft.entity.
mob.Mob
Entity
;
import
net.minecraft.util.math.Box
;
import
net.minecraft.util.math.Box
;
import
net.minecraft.util.math.Vec3d
;
import
net.minecraft.util.math.Vec3d
;
import
net.minecraft.world.World
;
import
net.minecraft.world.World
;
...
@@ -57,7 +57,7 @@ public class ClickHandler {
...
@@ -57,7 +57,7 @@ public class ClickHandler {
// Update the chat data manager on the client-side
// Update the chat data manager on the client-side
client
.
execute
(()
->
{
// Make sure to run on the client thread
client
.
execute
(()
->
{
// Make sure to run on the client thread
Entity
entity
=
ClientEntityFinder
.
getEntityByUUID
(
client
.
world
,
entityId
);
Mob
Entity
entity
=
ClientEntityFinder
.
getEntityByUUID
(
client
.
world
,
entityId
);
if
(
entity
!=
null
)
{
if
(
entity
!=
null
)
{
ChatDataManager
chatDataManager
=
ChatDataManager
.
getClientInstance
();
ChatDataManager
chatDataManager
=
ChatDataManager
.
getClientInstance
();
ChatDataManager
.
EntityChatData
chatData
=
chatDataManager
.
getOrCreateChatData
(
entity
.
getUuidAsString
());
ChatDataManager
.
EntityChatData
chatData
=
chatDataManager
.
getOrCreateChatData
(
entity
.
getUuidAsString
());
...
@@ -105,10 +105,10 @@ public class ClickHandler {
...
@@ -105,10 +105,10 @@ public class ClickHandler {
// Get all entities
// Get all entities
List
<
Entity
>
nearbyEntities
=
world
.
getOtherEntities
(
null
,
area
);
List
<
Entity
>
nearbyEntities
=
world
.
getOtherEntities
(
null
,
area
);
// Filter out
l
iving entities
// Filter out
MobEntity/L
iving entities
List
<
Living
Entity
>
nearbyCreatures
=
nearbyEntities
.
stream
()
List
<
Mob
Entity
>
nearbyCreatures
=
nearbyEntities
.
stream
()
.
filter
(
entity
->
entity
instanceof
Living
Entity
)
.
filter
(
entity
->
entity
instanceof
Mob
Entity
)
.
map
(
entity
->
(
Living
Entity
)
entity
)
.
map
(
entity
->
(
Mob
Entity
)
entity
)
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
// Get the player from the client
// Get the player from the client
...
@@ -121,11 +121,11 @@ public class ClickHandler {
...
@@ -121,11 +121,11 @@ public class ClickHandler {
Vec3d
lookVec
=
player
.
getRotationVec
(
1.0
F
);
Vec3d
lookVec
=
player
.
getRotationVec
(
1.0
F
);
Vec3d
endRay
=
startRay
.
add
(
lookVec
.
normalize
().
multiply
(
renderDistance
));
Vec3d
endRay
=
startRay
.
add
(
lookVec
.
normalize
().
multiply
(
renderDistance
));
Entity
closestEntity
=
null
;
Mob
Entity
closestEntity
=
null
;
double
closestDistance
=
Double
.
MAX_VALUE
;
// Start with the largest possible distance
double
closestDistance
=
Double
.
MAX_VALUE
;
// Start with the largest possible distance
// Iterate through the entities to check for hits
// Iterate through the entities to check for hits
for
(
Entity
entity
:
nearbyCreatures
)
{
for
(
Mob
Entity
entity
:
nearbyCreatures
)
{
if
(
entity
.
getType
()
==
EntityType
.
PLAYER
)
{
if
(
entity
.
getType
()
==
EntityType
.
PLAYER
)
{
// Skip Player
// Skip Player
continue
;
continue
;
...
...
src/client/java/com/owlmaddie/ClientEntityFinder.java
View file @
7bfd61e4
package
com
.
owlmaddie
;
package
com
.
owlmaddie
;
import
net.minecraft.entity.Entity
;
import
net.minecraft.client.world.ClientWorld
;
import
net.minecraft.client.world.ClientWorld
;
import
net.minecraft.entity.Entity
;
import
net.minecraft.entity.mob.MobEntity
;
import
java.util.UUID
;
import
java.util.UUID
;
// Find Client Entity from UUID
// Find Client Entity from UUID
public
class
ClientEntityFinder
{
public
class
ClientEntityFinder
{
public
static
Entity
getEntityByUUID
(
ClientWorld
world
,
UUID
uuid
)
{
public
static
Mob
Entity
getEntityByUUID
(
ClientWorld
world
,
UUID
uuid
)
{
for
(
Entity
entity
:
world
.
getEntities
())
{
for
(
Entity
entity
:
world
.
getEntities
())
{
if
(
entity
.
getUuid
().
equals
(
uuid
))
{
if
(
entity
.
getUuid
().
equals
(
uuid
)
&&
entity
instanceof
MobEntity
)
{
return
entity
;
return
(
MobEntity
)
entity
;
}
}
}
}
return
null
;
// Entity not found
return
null
;
// Entity not found
...
...
src/client/java/com/owlmaddie/ClientInit.java
View file @
7bfd61e4
...
@@ -13,7 +13,7 @@ import net.minecraft.client.render.entity.EntityRenderer;
...
@@ -13,7 +13,7 @@ import net.minecraft.client.render.entity.EntityRenderer;
import
net.minecraft.client.util.math.MatrixStack
;
import
net.minecraft.client.util.math.MatrixStack
;
import
net.minecraft.entity.Entity
;
import
net.minecraft.entity.Entity
;
import
net.minecraft.entity.EntityType
;
import
net.minecraft.entity.EntityType
;
import
net.minecraft.entity.
Living
Entity
;
import
net.minecraft.entity.
mob.Mob
Entity
;
import
net.minecraft.util.Identifier
;
import
net.minecraft.util.Identifier
;
import
net.minecraft.util.math.Box
;
import
net.minecraft.util.math.Box
;
import
net.minecraft.util.math.MathHelper
;
import
net.minecraft.util.math.MathHelper
;
...
@@ -140,7 +140,7 @@ public class ClientInit implements ClientModInitializer {
...
@@ -140,7 +140,7 @@ public class ClientInit implements ClientModInitializer {
RenderSystem
.
disableDepthTest
();
RenderSystem
.
disableDepthTest
();
}
}
private
void
drawEntityIcon
(
MatrixStack
matrices
,
Entity
entity
,
float
x
,
float
y
,
float
width
,
float
height
)
{
private
void
drawEntityIcon
(
MatrixStack
matrices
,
Mob
Entity
entity
,
float
x
,
float
y
,
float
width
,
float
height
)
{
// Get entity renderer
// Get entity renderer
EntityRenderer
renderer
=
EntityRendererAccessor
.
getEntityRenderer
(
entity
);
EntityRenderer
renderer
=
EntityRendererAccessor
.
getEntityRenderer
(
entity
);
String
entity_icon_path
=
renderer
.
getTexture
(
entity
).
getPath
();
String
entity_icon_path
=
renderer
.
getTexture
(
entity
).
getPath
();
...
@@ -200,7 +200,7 @@ public class ClientInit implements ClientModInitializer {
...
@@ -200,7 +200,7 @@ public class ClientInit implements ClientModInitializer {
false
,
matrix
,
immediate
,
TextLayerType
.
NORMAL
,
0
,
fullBright
);
false
,
matrix
,
immediate
,
TextLayerType
.
NORMAL
,
0
,
fullBright
);
}
}
private
void
drawEntityName
(
Entity
entity
,
Matrix4f
matrix
,
VertexConsumerProvider
immediate
,
private
void
drawEntityName
(
Mob
Entity
entity
,
Matrix4f
matrix
,
VertexConsumerProvider
immediate
,
int
fullBright
,
float
yOffset
)
{
int
fullBright
,
float
yOffset
)
{
if
(
entity
.
getCustomName
()
!=
null
)
{
if
(
entity
.
getCustomName
()
!=
null
)
{
TextRenderer
fontRenderer
=
MinecraftClient
.
getInstance
().
textRenderer
;
TextRenderer
fontRenderer
=
MinecraftClient
.
getInstance
().
textRenderer
;
...
@@ -235,13 +235,13 @@ public class ClientInit implements ClientModInitializer {
...
@@ -235,13 +235,13 @@ public class ClientInit implements ClientModInitializer {
// Get all entities
// Get all entities
List
<
Entity
>
nearbyEntities
=
world
.
getOtherEntities
(
null
,
area
);
List
<
Entity
>
nearbyEntities
=
world
.
getOtherEntities
(
null
,
area
);
// Filter
l
iving entities
// Filter
MobEntity/L
iving entities
List
<
Living
Entity
>
nearbyCreatures
=
nearbyEntities
.
stream
()
List
<
Mob
Entity
>
nearbyCreatures
=
nearbyEntities
.
stream
()
.
filter
(
entity
->
entity
instanceof
Living
Entity
)
.
filter
(
entity
->
entity
instanceof
Mob
Entity
)
.
map
(
entity
->
(
Living
Entity
)
entity
)
.
map
(
entity
->
(
Mob
Entity
)
entity
)
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
for
(
Entity
entity
:
nearbyCreatures
)
{
for
(
Mob
Entity
entity
:
nearbyCreatures
)
{
if
(
entity
.
getType
()
==
EntityType
.
PLAYER
)
{
if
(
entity
.
getType
()
==
EntityType
.
PLAYER
)
{
// Skip Player
// Skip Player
continue
;
continue
;
...
...
src/main/java/com/owlmaddie/ChatDataManager.java
View file @
7bfd61e4
...
@@ -9,7 +9,6 @@ import com.owlmaddie.json.QuestJson;
...
@@ -9,7 +9,6 @@ import com.owlmaddie.json.QuestJson;
import
com.owlmaddie.message.Behavior
;
import
com.owlmaddie.message.Behavior
;
import
com.owlmaddie.message.MessageParser
;
import
com.owlmaddie.message.MessageParser
;
import
com.owlmaddie.message.ParsedMessage
;
import
com.owlmaddie.message.ParsedMessage
;
import
net.minecraft.entity.LivingEntity
;
import
net.minecraft.entity.mob.MobEntity
;
import
net.minecraft.entity.mob.MobEntity
;
import
net.minecraft.item.ItemStack
;
import
net.minecraft.item.ItemStack
;
import
net.minecraft.server.MinecraftServer
;
import
net.minecraft.server.MinecraftServer
;
...
@@ -176,7 +175,7 @@ public class ChatDataManager {
...
@@ -176,7 +175,7 @@ public class ChatDataManager {
contextData
.
put
(
"world_moon_phase"
,
moonPhaseDescription
);
contextData
.
put
(
"world_moon_phase"
,
moonPhaseDescription
);
// Get Entity details
// Get Entity details
LivingEntity
entity
=
(
LivingEntity
)
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
UUID
.
fromString
(
entityId
));
MobEntity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
UUID
.
fromString
(
entityId
));
if
(
entity
.
getCustomName
()
==
null
)
{
if
(
entity
.
getCustomName
()
==
null
)
{
contextData
.
put
(
"entity_name"
,
""
);
contextData
.
put
(
"entity_name"
,
""
);
}
else
{
}
else
{
...
@@ -215,7 +214,7 @@ public class ChatDataManager {
...
@@ -215,7 +214,7 @@ public class ChatDataManager {
ParsedMessage
result
=
MessageParser
.
parseMessage
(
output_message
.
replace
(
"\n"
,
" "
));
ParsedMessage
result
=
MessageParser
.
parseMessage
(
output_message
.
replace
(
"\n"
,
" "
));
// Apply behaviors (if any)
// Apply behaviors (if any)
MobEntity
entity
=
(
MobEntity
)
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
UUID
.
fromString
(
entityId
));
MobEntity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
UUID
.
fromString
(
entityId
));
for
(
Behavior
behavior
:
result
.
getBehaviors
())
{
for
(
Behavior
behavior
:
result
.
getBehaviors
())
{
LOGGER
.
info
(
"Behavior: "
+
behavior
.
getName
()
+
(
behavior
.
getArgument
()
!=
null
?
LOGGER
.
info
(
"Behavior: "
+
behavior
.
getName
()
+
(
behavior
.
getArgument
()
!=
null
?
", Argument: "
+
behavior
.
getArgument
()
:
""
));
", Argument: "
+
behavior
.
getArgument
()
:
""
));
...
...
src/main/java/com/owlmaddie/ModInit.java
View file @
7bfd61e4
...
@@ -49,11 +49,11 @@ public class ModInit implements ModInitializer {
...
@@ -49,11 +49,11 @@ public class ModInit implements ModInitializer {
// Ensure that the task is synced with the server thread
// Ensure that the task is synced with the server thread
server
.
execute
(()
->
{
server
.
execute
(()
->
{
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
entityId
);
Mob
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
entityId
);
if
(
entity
!=
null
)
{
if
(
entity
!=
null
)
{
// Set talk to player goal (prevent entity from walking off)
// Set talk to player goal (prevent entity from walking off)
TalkPlayerGoal
talkGoal
=
new
TalkPlayerGoal
(
player
,
(
MobEntity
)
entity
,
3.5
F
);
TalkPlayerGoal
talkGoal
=
new
TalkPlayerGoal
(
player
,
entity
,
3.5
F
);
EntityBehaviorManager
.
addGoal
(
(
MobEntity
)
entity
,
talkGoal
,
GoalPriority
.
TALK_PLAYER
);
EntityBehaviorManager
.
addGoal
(
entity
,
talkGoal
,
GoalPriority
.
TALK_PLAYER
);
ChatDataManager
.
EntityChatData
chatData
=
ChatDataManager
.
getServerInstance
().
getOrCreateChatData
(
entity
.
getUuidAsString
());
ChatDataManager
.
EntityChatData
chatData
=
ChatDataManager
.
getServerInstance
().
getOrCreateChatData
(
entity
.
getUuidAsString
());
if
(
chatData
.
status
==
ChatDataManager
.
ChatStatus
.
NONE
||
if
(
chatData
.
status
==
ChatDataManager
.
ChatStatus
.
NONE
||
...
@@ -83,11 +83,11 @@ public class ModInit implements ModInitializer {
...
@@ -83,11 +83,11 @@ public class ModInit implements ModInitializer {
// Ensure that the task is synced with the server thread
// Ensure that the task is synced with the server thread
server
.
execute
(()
->
{
server
.
execute
(()
->
{
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
entityId
);
Mob
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
entityId
);
if
(
entity
!=
null
)
{
if
(
entity
!=
null
)
{
// Set talk to player goal (prevent entity from walking off)
// Set talk to player goal (prevent entity from walking off)
TalkPlayerGoal
talkGoal
=
new
TalkPlayerGoal
(
player
,
(
MobEntity
)
entity
,
3.5
F
);
TalkPlayerGoal
talkGoal
=
new
TalkPlayerGoal
(
player
,
entity
,
3.5
F
);
EntityBehaviorManager
.
addGoal
(
(
MobEntity
)
entity
,
talkGoal
,
GoalPriority
.
TALK_PLAYER
);
EntityBehaviorManager
.
addGoal
(
entity
,
talkGoal
,
GoalPriority
.
TALK_PLAYER
);
ChatDataManager
.
EntityChatData
chatData
=
ChatDataManager
.
getServerInstance
().
getOrCreateChatData
(
entity
.
getUuidAsString
());
ChatDataManager
.
EntityChatData
chatData
=
ChatDataManager
.
getServerInstance
().
getOrCreateChatData
(
entity
.
getUuidAsString
());
if
(
chatData
.
status
==
ChatDataManager
.
ChatStatus
.
DISPLAY
)
{
if
(
chatData
.
status
==
ChatDataManager
.
ChatStatus
.
DISPLAY
)
{
...
@@ -105,11 +105,11 @@ public class ModInit implements ModInitializer {
...
@@ -105,11 +105,11 @@ public class ModInit implements ModInitializer {
// Ensure that the task is synced with the server thread
// Ensure that the task is synced with the server thread
server
.
execute
(()
->
{
server
.
execute
(()
->
{
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
entityId
);
Mob
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
entityId
);
if
(
entity
!=
null
)
{
if
(
entity
!=
null
)
{
// Set talk to player goal (prevent entity from walking off)
// Set talk to player goal (prevent entity from walking off)
TalkPlayerGoal
talkGoal
=
new
TalkPlayerGoal
(
player
,
(
MobEntity
)
entity
,
7
F
);
TalkPlayerGoal
talkGoal
=
new
TalkPlayerGoal
(
player
,
entity
,
7
F
);
EntityBehaviorManager
.
addGoal
(
(
MobEntity
)
entity
,
talkGoal
,
GoalPriority
.
TALK_PLAYER
);
EntityBehaviorManager
.
addGoal
(
entity
,
talkGoal
,
GoalPriority
.
TALK_PLAYER
);
}
}
});
});
});
});
...
@@ -121,11 +121,11 @@ public class ModInit implements ModInitializer {
...
@@ -121,11 +121,11 @@ public class ModInit implements ModInitializer {
// Ensure that the task is synced with the server thread
// Ensure that the task is synced with the server thread
server
.
execute
(()
->
{
server
.
execute
(()
->
{
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
entityId
);
Mob
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
player
.
getServerWorld
(),
entityId
);
if
(
entity
!=
null
)
{
if
(
entity
!=
null
)
{
// Set talk to player goal (prevent entity from walking off)
// Set talk to player goal (prevent entity from walking off)
TalkPlayerGoal
talkGoal
=
new
TalkPlayerGoal
(
player
,
(
MobEntity
)
entity
,
3.5
F
);
TalkPlayerGoal
talkGoal
=
new
TalkPlayerGoal
(
player
,
entity
,
3.5
F
);
EntityBehaviorManager
.
addGoal
(
(
MobEntity
)
entity
,
talkGoal
,
GoalPriority
.
TALK_PLAYER
);
EntityBehaviorManager
.
addGoal
(
entity
,
talkGoal
,
GoalPriority
.
TALK_PLAYER
);
ChatDataManager
.
EntityChatData
chatData
=
ChatDataManager
.
getServerInstance
().
getOrCreateChatData
(
entity
.
getUuidAsString
());
ChatDataManager
.
EntityChatData
chatData
=
ChatDataManager
.
getServerInstance
().
getOrCreateChatData
(
entity
.
getUuidAsString
());
if
(
chatData
.
status
==
ChatDataManager
.
ChatStatus
.
END
)
{
if
(
chatData
.
status
==
ChatDataManager
.
ChatStatus
.
END
)
{
...
@@ -174,7 +174,7 @@ public class ModInit implements ModInitializer {
...
@@ -174,7 +174,7 @@ public class ModInit implements ModInitializer {
public
static
void
BroadcastPacketMessage
(
ChatDataManager
.
EntityChatData
chatData
)
{
public
static
void
BroadcastPacketMessage
(
ChatDataManager
.
EntityChatData
chatData
)
{
for
(
ServerWorld
world
:
serverInstance
.
getWorlds
())
{
for
(
ServerWorld
world
:
serverInstance
.
getWorlds
())
{
UUID
entityId
=
UUID
.
fromString
(
chatData
.
entityId
);
UUID
entityId
=
UUID
.
fromString
(
chatData
.
entityId
);
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
world
,
entityId
);
Mob
Entity
entity
=
ServerEntityFinder
.
getEntityByUUID
(
world
,
entityId
);
if
(
entity
!=
null
)
{
if
(
entity
!=
null
)
{
// Set custom name (if none)
// Set custom name (if none)
if
(
entity
.
getCustomName
()
==
null
&&
chatData
.
status
!=
ChatDataManager
.
ChatStatus
.
PENDING
)
{
if
(
entity
.
getCustomName
()
==
null
&&
chatData
.
status
!=
ChatDataManager
.
ChatStatus
.
PENDING
)
{
...
...
src/main/java/com/owlmaddie/ServerEntityFinder.java
View file @
7bfd61e4
package
com
.
owlmaddie
;
package
com
.
owlmaddie
;
import
net.minecraft.entity.Entity
;
import
net.minecraft.entity.Entity
;
import
net.minecraft.entity.mob.MobEntity
;
import
net.minecraft.server.world.ServerWorld
;
import
net.minecraft.server.world.ServerWorld
;
import
java.util.UUID
;
import
java.util.UUID
;
// Find Server Entity from UUID
// Find Server Entity from UUID
public
class
ServerEntityFinder
{
public
class
ServerEntityFinder
{
public
static
Entity
getEntityByUUID
(
ServerWorld
world
,
UUID
uuid
)
{
public
static
Mob
Entity
getEntityByUUID
(
ServerWorld
world
,
UUID
uuid
)
{
for
(
Entity
entity
:
world
.
iterateEntities
())
{
for
(
Entity
entity
:
world
.
iterateEntities
())
{
if
(
entity
.
getUuid
().
equals
(
uuid
))
{
if
(
entity
.
getUuid
().
equals
(
uuid
)
&&
entity
instanceof
MobEntity
)
{
return
entity
;
return
(
MobEntity
)
entity
;
}
}
}
}
return
null
;
// Entity not found
return
null
;
// Entity not found
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment