Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94ffe6e7b7 | ||
|
|
4121c59484 | ||
|
|
c267b62afa | ||
|
|
cde0e28e44 | ||
|
|
18c3d6fc5d | ||
|
|
942cd59db8 | ||
|
|
7faef2e976 | ||
|
|
7f21b40d93 | ||
|
|
3b21cf3182 | ||
|
|
9e3df6c691 | ||
|
|
2cb8a7fb8f | ||
|
|
09e6b4cc90 | ||
|
|
e6a442c98b | ||
|
|
cce8fd3280 | ||
|
|
ffee63dc57 | ||
|
|
2907fabe85 | ||
|
|
3f3136c453 | ||
|
|
84afc199fa | ||
|
|
fecbefc15c | ||
|
|
a9e546a121 | ||
|
|
98220921bd | ||
|
|
42750356b5 | ||
|
|
753a34abd5 | ||
|
|
020ede82b6 | ||
|
|
25de3bf08e | ||
|
|
67573fad26 | ||
|
|
1b7d6af7f5 | ||
|
|
ff1ebef34f | ||
|
|
d4b780229d | ||
|
|
c718fb343d | ||
|
|
bed8e91bc0 | ||
|
|
2bed6aae4f | ||
|
|
94473ab1b0 | ||
|
|
454001cca8 |
@@ -0,0 +1,26 @@
|
||||
# Promiscuity - Project Overview
|
||||
|
||||
This project is a multi-layered application consisting of a Godot-based game and a backend powered by .NET microservices and MongoDB.
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `game/`: The Godot 4.6 game project.
|
||||
- `microservices/`: ASP.NET Core 8.0 microservices providing backend logic (Auth, Character, Crafting, Inventory, Locations, Mail, and World).
|
||||
- `.gitea/workflows/`: CI/CD pipelines for deploying microservices to Kubernetes.
|
||||
|
||||
## Core Mandates
|
||||
|
||||
- **Godot Development**: Follow guidelines in `game/GEMINI.md`.
|
||||
- **Microservices Development**: Follow guidelines in `microservices/GEMINI.md`.
|
||||
- **Infrastructure**: Deployment is handled via K8s. Dockerfiles are located in each microservice directory.
|
||||
|
||||
## Getting Started
|
||||
|
||||
- **Microservices**: Each microservice can be run individually or via the `micro-services.sln` solution file. They require a MongoDB instance (default: `mongodb://127.0.0.1:27017`).
|
||||
- **Game**: Open `game/project.godot` in Godot Engine 4.6+.
|
||||
|
||||
## Shared Conventions
|
||||
|
||||
- **Naming**: Use PascalCase for C# (microservices) and snake_case for GDScript (game), as is idiomatic for each platform.
|
||||
- **Documentation**: Maintain `DOCUMENTS.md` in microservice directories for API shapes and document models.
|
||||
- **Communication**: The game communicates with microservices via HTTP/REST.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.cs text diff=csharp
|
||||
*.gd text
|
||||
*.tscn text
|
||||
*.tres text
|
||||
*.json text
|
||||
*.md text
|
||||
*.xml text
|
||||
*.yml text
|
||||
*.yaml text
|
||||
*.csproj text
|
||||
*.sln text
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.bat text eol=crlf
|
||||
*.ps1 text eol=crlf
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.mov binary
|
||||
*.mp4 binary
|
||||
*.mp3 binary
|
||||
*.wav binary
|
||||
*.ogg binary
|
||||
*.ttf binary
|
||||
*.otf binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
*.eot binary
|
||||
*.pdf binary
|
||||
*.zip binary
|
||||
*.7z binary
|
||||
*.import binary
|
||||
*.uid binary
|
||||
*.glb filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -1,80 +1,97 @@
|
||||
name: Deploy Promiscuity Auth API
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
|
||||
env:
|
||||
IMAGE_NAME: promiscuity-auth:latest
|
||||
IMAGE_TAR: /tmp/promiscuity-auth.tar
|
||||
# All nodes that might run the pod (control-plane + workers)
|
||||
NODES: "192.168.86.72 192.168.86.73 192.168.86.74"
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# -----------------------------
|
||||
# Build Docker image
|
||||
# -----------------------------
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
cd microservices/AuthApi
|
||||
docker build -t "${IMAGE_NAME}" .
|
||||
|
||||
# -----------------------------
|
||||
# Save image as TAR on runner
|
||||
# -----------------------------
|
||||
- name: Save Docker image to TAR
|
||||
run: |
|
||||
docker save "${IMAGE_NAME}" -o "${IMAGE_TAR}"
|
||||
|
||||
# -----------------------------
|
||||
# Copy TAR to each Kubernetes node
|
||||
# -----------------------------
|
||||
- name: Copy TAR to nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Copying image tar to $node ..."
|
||||
scp -o StrictHostKeyChecking=no "${IMAGE_TAR}" hz@"$node":/tmp/promiscuity-auth.tar
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# Import image into containerd on each node
|
||||
# -----------------------------
|
||||
- name: Import image on nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Importing image on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "sudo ctr -n k8s.io images import /tmp/promiscuity-auth.tar"
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# CLEANUP: delete TAR from nodes
|
||||
# -----------------------------
|
||||
- name: Clean TAR from nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Removing image tar on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "rm -f /tmp/promiscuity-auth.tar"
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# CLEANUP: delete TAR from runner
|
||||
# -----------------------------
|
||||
- name: Clean TAR on runner
|
||||
run: |
|
||||
rm -f "${IMAGE_TAR}"
|
||||
|
||||
# -----------------------------
|
||||
# Write kubeconfig from secret
|
||||
# -----------------------------
|
||||
name: Deploy Promiscuity Auth API
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "microservices/AuthApi/**"
|
||||
- ".gitea/workflows/deploy-auth.yml"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
|
||||
env:
|
||||
IMAGE_NAME: promiscuity-auth:latest
|
||||
IMAGE_TAR: /tmp/promiscuity-auth.tar
|
||||
# All nodes that might run the pod (control-plane + workers)
|
||||
NODES: "192.168.86.72 192.168.86.73 192.168.86.74"
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Reclaim Docker build space
|
||||
run: |
|
||||
rm -f "${IMAGE_TAR}"
|
||||
docker container prune -f
|
||||
docker image prune -f
|
||||
docker image prune -af --filter "until=24h"
|
||||
docker builder prune -af || true
|
||||
docker system df
|
||||
df -h
|
||||
|
||||
# -----------------------------
|
||||
# Build Docker image
|
||||
# -----------------------------
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
cd microservices/AuthApi
|
||||
docker build -t "${IMAGE_NAME}" .
|
||||
|
||||
# -----------------------------
|
||||
# Save image as TAR on runner
|
||||
# -----------------------------
|
||||
- name: Save Docker image to TAR
|
||||
run: |
|
||||
docker save "${IMAGE_NAME}" -o "${IMAGE_TAR}"
|
||||
|
||||
# -----------------------------
|
||||
# Copy TAR to each Kubernetes node
|
||||
# -----------------------------
|
||||
- name: Copy TAR to nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Copying image tar to $node ..."
|
||||
scp -o StrictHostKeyChecking=no "${IMAGE_TAR}" hz@"$node":/tmp/promiscuity-auth.tar
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# Import image into containerd on each node
|
||||
# -----------------------------
|
||||
- name: Import image on nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Importing image on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "sudo ctr -n k8s.io images import /tmp/promiscuity-auth.tar"
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# CLEANUP: delete TAR from nodes
|
||||
# -----------------------------
|
||||
- name: Clean TAR from nodes
|
||||
if: always()
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Removing image tar on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "rm -f /tmp/promiscuity-auth.tar" || true
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# CLEANUP: delete TAR from runner
|
||||
# -----------------------------
|
||||
- name: Clean TAR on runner
|
||||
if: always()
|
||||
run: |
|
||||
rm -f "${IMAGE_TAR}"
|
||||
docker image rm "${IMAGE_NAME}" 2>/dev/null || true
|
||||
docker image prune -f
|
||||
|
||||
# -----------------------------
|
||||
# Write kubeconfig from secret
|
||||
# -----------------------------
|
||||
- name: Write kubeconfig from secret
|
||||
env:
|
||||
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
|
||||
@@ -91,23 +108,33 @@ jobs:
|
||||
run: |
|
||||
kubectl create namespace promiscuity-auth --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
- name: Configure internal API secret
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
INTERNAL_PURGE_SECRET: ${{ secrets.INTERNAL_PURGE_SECRET }}
|
||||
run: |
|
||||
test -n "$INTERNAL_PURGE_SECRET"
|
||||
kubectl create secret generic medmind-internal-api \
|
||||
--from-literal=purge-secret="$INTERNAL_PURGE_SECRET" \
|
||||
--dry-run=client -o yaml | kubectl apply -n promiscuity-auth -f -
|
||||
|
||||
# -----------------------------
|
||||
# Apply Kubernetes manifests
|
||||
# (You create these files in your repo)
|
||||
# -----------------------------
|
||||
- name: Apply Auth deployment & service
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl apply -f microservices/AuthApi/k8s/deployment.yaml -n promiscuity-auth
|
||||
kubectl apply -f microservices/AuthApi/k8s/service.yaml -n promiscuity-auth
|
||||
|
||||
# -----------------------------
|
||||
# Rollout restart & wait
|
||||
# -----------------------------
|
||||
- name: Restart Auth deployment
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl rollout restart deployment/promiscuity-auth -n promiscuity-auth
|
||||
kubectl rollout status deployment/promiscuity-auth -n promiscuity-auth
|
||||
- name: Apply Auth deployment & service
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl apply -f microservices/AuthApi/k8s/deployment.yaml -n promiscuity-auth
|
||||
kubectl apply -f microservices/AuthApi/k8s/service.yaml -n promiscuity-auth
|
||||
|
||||
# -----------------------------
|
||||
# Rollout restart & wait
|
||||
# -----------------------------
|
||||
- name: Restart Auth deployment
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl rollout restart deployment/promiscuity-auth -n promiscuity-auth
|
||||
kubectl rollout status deployment/promiscuity-auth -n promiscuity-auth
|
||||
|
||||
@@ -1,80 +1,82 @@
|
||||
name: Deploy Promiscuity Character API
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
|
||||
env:
|
||||
IMAGE_NAME: promiscuity-character:latest
|
||||
IMAGE_TAR: /tmp/promiscuity-character.tar
|
||||
# All nodes that might run the pod (control-plane + workers)
|
||||
NODES: "192.168.86.72 192.168.86.73 192.168.86.74"
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# -----------------------------
|
||||
# Build Docker image
|
||||
# -----------------------------
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
cd microservices/CharacterApi
|
||||
docker build -t "${IMAGE_NAME}" .
|
||||
|
||||
# -----------------------------
|
||||
# Save image as TAR on runner
|
||||
# -----------------------------
|
||||
- name: Save Docker image to TAR
|
||||
run: |
|
||||
docker save "${IMAGE_NAME}" -o "${IMAGE_TAR}"
|
||||
|
||||
# -----------------------------
|
||||
# Copy TAR to each Kubernetes node
|
||||
# -----------------------------
|
||||
- name: Copy TAR to nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Copying image tar to $node ..."
|
||||
scp -o StrictHostKeyChecking=no "${IMAGE_TAR}" hz@"$node":/tmp/promiscuity-character.tar
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# Import image into containerd on each node
|
||||
# -----------------------------
|
||||
- name: Import image on nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Importing image on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "sudo ctr -n k8s.io images import /tmp/promiscuity-character.tar"
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# CLEANUP: delete TAR from nodes
|
||||
# -----------------------------
|
||||
- name: Clean TAR from nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Removing image tar on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "rm -f /tmp/promiscuity-character.tar"
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# CLEANUP: delete TAR from runner
|
||||
# -----------------------------
|
||||
- name: Clean TAR on runner
|
||||
run: |
|
||||
rm -f "${IMAGE_TAR}"
|
||||
|
||||
# -----------------------------
|
||||
# Write kubeconfig from secret
|
||||
# -----------------------------
|
||||
name: Deploy Promiscuity Character API
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "microservices/CharacterApi/**"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
|
||||
env:
|
||||
IMAGE_NAME: promiscuity-character:latest
|
||||
IMAGE_TAR: /tmp/promiscuity-character.tar
|
||||
# All nodes that might run the pod (control-plane + workers)
|
||||
NODES: "192.168.86.72 192.168.86.73 192.168.86.74"
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# -----------------------------
|
||||
# Build Docker image
|
||||
# -----------------------------
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
cd microservices/CharacterApi
|
||||
docker build -t "${IMAGE_NAME}" .
|
||||
|
||||
# -----------------------------
|
||||
# Save image as TAR on runner
|
||||
# -----------------------------
|
||||
- name: Save Docker image to TAR
|
||||
run: |
|
||||
docker save "${IMAGE_NAME}" -o "${IMAGE_TAR}"
|
||||
|
||||
# -----------------------------
|
||||
# Copy TAR to each Kubernetes node
|
||||
# -----------------------------
|
||||
- name: Copy TAR to nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Copying image tar to $node ..."
|
||||
scp -o StrictHostKeyChecking=no "${IMAGE_TAR}" hz@"$node":/tmp/promiscuity-character.tar
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# Import image into containerd on each node
|
||||
# -----------------------------
|
||||
- name: Import image on nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Importing image on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "sudo ctr -n k8s.io images import /tmp/promiscuity-character.tar"
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# CLEANUP: delete TAR from nodes
|
||||
# -----------------------------
|
||||
- name: Clean TAR from nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Removing image tar on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "rm -f /tmp/promiscuity-character.tar"
|
||||
done
|
||||
|
||||
# -----------------------------
|
||||
# CLEANUP: delete TAR from runner
|
||||
# -----------------------------
|
||||
- name: Clean TAR on runner
|
||||
run: |
|
||||
rm -f "${IMAGE_TAR}"
|
||||
|
||||
# -----------------------------
|
||||
# Write kubeconfig from secret
|
||||
# -----------------------------
|
||||
- name: Write kubeconfig from secret
|
||||
env:
|
||||
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
|
||||
@@ -94,19 +96,19 @@ jobs:
|
||||
# -----------------------------
|
||||
# Apply Kubernetes manifests
|
||||
# -----------------------------
|
||||
- name: Apply Character deployment & service
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl apply -f microservices/CharacterApi/k8s/deployment.yaml -n promiscuity-character
|
||||
kubectl apply -f microservices/CharacterApi/k8s/service.yaml -n promiscuity-character
|
||||
|
||||
# -----------------------------
|
||||
# Rollout restart & wait
|
||||
# -----------------------------
|
||||
- name: Restart Character deployment
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl rollout restart deployment/promiscuity-character -n promiscuity-character
|
||||
kubectl rollout status deployment/promiscuity-character -n promiscuity-character
|
||||
- name: Apply Character deployment & service
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl apply -f microservices/CharacterApi/k8s/deployment.yaml -n promiscuity-character
|
||||
kubectl apply -f microservices/CharacterApi/k8s/service.yaml -n promiscuity-character
|
||||
|
||||
# -----------------------------
|
||||
# Rollout restart & wait
|
||||
# -----------------------------
|
||||
- name: Restart Character deployment
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl rollout restart deployment/promiscuity-character -n promiscuity-character
|
||||
kubectl rollout status deployment/promiscuity-character -n promiscuity-character
|
||||
|
||||
@@ -4,6 +4,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "microservices/CraftingApi/**"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -4,6 +4,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "microservices/InventoryApi/**"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -4,6 +4,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "microservices/LocationsApi/**"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -4,6 +4,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "microservices/MailApi/**"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
name: Deploy Promiscuity World API
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "microservices/WorldApi/**"
|
||||
workflow_dispatch: {}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
|
||||
env:
|
||||
IMAGE_NAME: promiscuity-world:latest
|
||||
IMAGE_TAR: /tmp/promiscuity-world.tar
|
||||
NODES: "192.168.86.72 192.168.86.73 192.168.86.74"
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
cd microservices/WorldApi
|
||||
docker build -t "${IMAGE_NAME}" .
|
||||
|
||||
- name: Save Docker image to TAR
|
||||
run: |
|
||||
docker save "${IMAGE_NAME}" -o "${IMAGE_TAR}"
|
||||
|
||||
- name: Copy TAR to nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Copying image tar to $node ..."
|
||||
scp -o StrictHostKeyChecking=no "${IMAGE_TAR}" hz@"$node":/tmp/promiscuity-world.tar
|
||||
done
|
||||
|
||||
- name: Import image on nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Importing image on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "sudo ctr -n k8s.io images import /tmp/promiscuity-world.tar"
|
||||
done
|
||||
|
||||
- name: Clean TAR from nodes
|
||||
run: |
|
||||
for node in ${NODES}; do
|
||||
echo "Removing image tar on $node ..."
|
||||
ssh -o StrictHostKeyChecking=no hz@"$node" "rm -f /tmp/promiscuity-world.tar"
|
||||
done
|
||||
|
||||
- name: Clean TAR on runner
|
||||
run: |
|
||||
rm -f "${IMAGE_TAR}"
|
||||
|
||||
- name: Write kubeconfig from secret
|
||||
env:
|
||||
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
|
||||
run: |
|
||||
mkdir -p /tmp/kube
|
||||
printf '%s\n' "$KUBECONFIG_CONTENT" > /tmp/kube/config
|
||||
|
||||
- name: Create namespace if missing
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl create namespace promiscuity-world --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
- name: Apply World deployment & service
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl apply -f microservices/WorldApi/k8s/deployment.yaml -n promiscuity-world
|
||||
kubectl apply -f microservices/WorldApi/k8s/service.yaml -n promiscuity-world
|
||||
|
||||
- name: Restart World deployment
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl rollout restart deployment/promiscuity-world -n promiscuity-world
|
||||
kubectl rollout status deployment/promiscuity-world -n promiscuity-world
|
||||
@@ -1,27 +1,27 @@
|
||||
name: k8s smoke test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Write kubeconfig from secret
|
||||
env:
|
||||
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
|
||||
run: |
|
||||
mkdir -p /tmp/kube
|
||||
printf '%s\n' "$KUBECONFIG_CONTENT" > /tmp/kube/config
|
||||
|
||||
- name: Test kubectl connectivity
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl get nodes --kubeconfig "${KUBECONFIG}"
|
||||
name: k8s smoke test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Write kubeconfig from secret
|
||||
env:
|
||||
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
|
||||
run: |
|
||||
mkdir -p /tmp/kube
|
||||
printf '%s\n' "$KUBECONFIG_CONTENT" > /tmp/kube/config
|
||||
|
||||
- name: Test kubectl connectivity
|
||||
env:
|
||||
KUBECONFIG: /tmp/kube/config
|
||||
run: |
|
||||
kubectl get nodes --kubeconfig "${KUBECONFIG}"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.aider*
|
||||
@@ -18,5 +18,9 @@
|
||||
- Sprint: Shift
|
||||
- Interact (enter/exit car): E
|
||||
- Flashlight: F
|
||||
- Radial command menu: Q
|
||||
- Fireball: Shift + B
|
||||
- Phone: Tab
|
||||
- Pause menu: Esc
|
||||
- Toggle first/third person: V
|
||||
- Zoom (in/out): Scroll Wheel (snaps to First Person on zoom in)
|
||||
|
||||
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.6 MiB |
@@ -0,0 +1,50 @@
|
||||
# Godot Game Development - GEMINI.md
|
||||
|
||||
This directory contains the Godot 4.6 game project for "Promiscuity".
|
||||
|
||||
## Core Mandates
|
||||
|
||||
- **Engine Version**: Godot 4.6 (Forward Plus).
|
||||
- **Language**: GDScript is the primary scripting language. C# is enabled but used only when performance or specific library needs arise.
|
||||
- **Naming Conventions**:
|
||||
- Files/Folders: `snake_case.gd`, `snake_case.tscn`.
|
||||
- Variables/Functions: `snake_case`.
|
||||
- Constants: `SCREAMING_SNAKE_CASE`.
|
||||
- Classes: `PascalCase`.
|
||||
- **Autoloads**: Use the established singletons for global state and services:
|
||||
- `AuthState`: JWT authentication and session.
|
||||
- `CharacterService`: API calls for character management.
|
||||
- `SelectedCharacter`: Tracking the currently active character.
|
||||
- `QuestManager`: Game quest progression.
|
||||
- `DialogSystem`: UI dialog and interaction.
|
||||
- `TeleportState`: Handling transitions between levels.
|
||||
- `MenuMusic` / `MenuSfx`: Audio management.
|
||||
- `SimpleGrass`: Singleton for grass rendering.
|
||||
- **Node Paths**: Prefer `unique names` (%NodeName) or `@onready` variables for node references. Avoid fragile string paths.
|
||||
|
||||
## Asset Pipeline
|
||||
|
||||
- **Models**: Blender files (`.blend`) and GLB files are supported. Blender integration is preferred for easy editing.
|
||||
- **Audio**: Use `.ogg` for music/loops and `.wav` for short sound effects.
|
||||
- **UI**: Themes are stored in `themes/`. Adhere to established UI patterns.
|
||||
|
||||
## Project Organization
|
||||
|
||||
- `scenes/`: Scene files and associated scripts.
|
||||
- `Characters/`: Player and NPC scenes.
|
||||
- `Levels/`: Game world/environments.
|
||||
- `UI/`: Menus, HUDs, and UI components.
|
||||
- `Interaction/`: Interactive objects and systems (e.g., RadialCommandMenu).
|
||||
- `Projectiles/`: Projectiles like fireballs.
|
||||
- `Quests/`: Quest-related scenes and logic.
|
||||
- `Vehicles/`: Controllable vehicles.
|
||||
- `CardGame/`: Minigame components.
|
||||
- `assets/`: Raw assets (textures, models, audio).
|
||||
- `addons/`: Third-party plugins (e.g., `simplegrasstextured`, `godot_mcp`).
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Signals**: Use signals for decoupled communication between nodes.
|
||||
- **Resources**: Encapsulate data in custom `Resource` scripts for modularity.
|
||||
- **Tool Scripts**: Use `@tool` carefully for editor-side logic.
|
||||
- **Physics**: Use `_physics_process` for movement and interaction logic.
|
||||
@@ -0,0 +1 @@
|
||||
uid://mcipi7y664aq
|
||||
@@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Godot MCP"
|
||||
description="A plugin to enable communication between Godot Editor and Model Context Protocol (MCP) clients."
|
||||
author="Your Name"
|
||||
version="0.1.0"
|
||||
script="plugin.gd"
|
||||
@@ -0,0 +1,140 @@
|
||||
# Structure for addons/godot_mcp/plugin.gd
|
||||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
const SERVER_PORT = 6400
|
||||
var server: TCPServer = null
|
||||
var active_connections = []
|
||||
var command_handler
|
||||
|
||||
func _enter_tree():
|
||||
# Initialize the plugin
|
||||
print("Godot MCP Plugin activated")
|
||||
|
||||
# Create command handler
|
||||
command_handler = preload("res://addons/godot_mcp/command_handler.gd").new()
|
||||
command_handler.set_editor_plugin(self)
|
||||
|
||||
# Start the TCP server
|
||||
server = TCPServer.new()
|
||||
var error = server.listen(SERVER_PORT)
|
||||
if error != OK:
|
||||
push_error("Failed to start Godot MCP Server on port %d: %s" % [SERVER_PORT, error])
|
||||
return
|
||||
|
||||
print("Godot MCP Server listening on port %d" % SERVER_PORT)
|
||||
|
||||
# Add UI
|
||||
add_control_to_bottom_panel(
|
||||
preload("res://addons/godot_mcp/ui/mcp_panel.tscn").instantiate(),
|
||||
"MCP"
|
||||
)
|
||||
|
||||
func _exit_tree():
|
||||
# Clean up the plugin when disabled
|
||||
if server:
|
||||
server.stop()
|
||||
server = null
|
||||
|
||||
for connection in active_connections:
|
||||
if connection.get_status() == StreamPeerTCP.STATUS_CONNECTED:
|
||||
connection.disconnect_from_host()
|
||||
|
||||
active_connections.clear()
|
||||
|
||||
# Remove UI
|
||||
remove_control_from_bottom_panel(get_editor_interface().get_base_control().get_node("MCPPanel"))
|
||||
print("Godot MCP Plugin deactivated")
|
||||
|
||||
func _process(delta):
|
||||
# Check for new connections
|
||||
if server and server.is_connection_available():
|
||||
var connection = server.take_connection()
|
||||
if connection:
|
||||
active_connections.append(connection)
|
||||
print("New MCP connection established")
|
||||
|
||||
# Process existing connections
|
||||
var i = 0
|
||||
while i < active_connections.size():
|
||||
var connection = active_connections[i]
|
||||
|
||||
# Check connection status
|
||||
if connection.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||
active_connections.remove_at(i)
|
||||
print("MCP connection closed")
|
||||
continue
|
||||
|
||||
# Check for incoming messages
|
||||
if connection.get_available_bytes() > 0:
|
||||
var data = _read_message(connection)
|
||||
if data.size() > 0:
|
||||
# Process the command
|
||||
var response = _process_command(data)
|
||||
|
||||
# Send the response
|
||||
_send_message(connection, response)
|
||||
|
||||
i += 1
|
||||
|
||||
func _read_message(connection):
|
||||
# Read data from the connection
|
||||
var data = PackedByteArray()
|
||||
var bytes_available = connection.get_available_bytes()
|
||||
|
||||
if bytes_available > 0:
|
||||
data = connection.get_data(bytes_available)[1]
|
||||
|
||||
# Attempt to parse as JSON
|
||||
var json_string = data.get_string_from_utf8()
|
||||
var json = JSON.new()
|
||||
var error = json.parse(json_string)
|
||||
|
||||
if error == OK:
|
||||
return json.get_data()
|
||||
else:
|
||||
print("Failed to parse JSON: ", json.get_error_message())
|
||||
|
||||
return {}
|
||||
|
||||
func _send_message(connection, data):
|
||||
# Convert to JSON and send
|
||||
var json_string = JSON.stringify(data)
|
||||
connection.put_data(json_string.to_utf8_buffer())
|
||||
|
||||
|
||||
|
||||
func _process_command(data):
|
||||
# Process the command and return a response
|
||||
if data == null or typeof(data) != TYPE_DICTIONARY:
|
||||
return {
|
||||
"status": "error",
|
||||
"error": "Invalid command format. Expected a dictionary."
|
||||
}
|
||||
|
||||
if not data.has("type") or not data.has("params"):
|
||||
return {
|
||||
"status": "error",
|
||||
"error": "Invalid command format. Expected 'type' and 'params' fields."
|
||||
}
|
||||
|
||||
var command_type = data["type"]
|
||||
var params = data["params"]
|
||||
|
||||
if command_type == "ping":
|
||||
return {"status": "success", "result": {"message": "pong"}}
|
||||
|
||||
# Forward to command handler
|
||||
var result = command_handler.handle_command(command_type, params)
|
||||
|
||||
# Check if result is valid
|
||||
if result == null:
|
||||
return {
|
||||
"status": "error",
|
||||
"error": "Command handler returned null result"
|
||||
}
|
||||
|
||||
if result.has("error"):
|
||||
return {"status": "error", "error": result.error}
|
||||
else:
|
||||
return {"status": "success", "result": result}
|
||||
@@ -0,0 +1 @@
|
||||
uid://ddfhkiyge45tn
|
||||
@@ -0,0 +1,77 @@
|
||||
# addons/godot_mcp/ui/mcp_panel.gd
|
||||
@tool
|
||||
extends Control
|
||||
|
||||
var status_label: Label
|
||||
var port_field: SpinBox
|
||||
var start_button: Button
|
||||
var stop_button: Button
|
||||
var log_display: TextEdit
|
||||
|
||||
func _ready():
|
||||
# Set up references to UI elements
|
||||
status_label = $VBoxContainer/StatusPanel/StatusLabel
|
||||
port_field = $VBoxContainer/ConfigPanel/PortField
|
||||
start_button = $VBoxContainer/ButtonPanel/StartButton
|
||||
stop_button = $VBoxContainer/ButtonPanel/StopButton
|
||||
log_display = $VBoxContainer/LogPanel/LogDisplay
|
||||
|
||||
# Initialize UI
|
||||
port_field.value = 6400 # Default port
|
||||
start_button.disabled = false
|
||||
stop_button.disabled = true
|
||||
|
||||
# Connect signals
|
||||
start_button.pressed.connect(_on_start_button_pressed)
|
||||
stop_button.pressed.connect(_on_stop_button_pressed)
|
||||
|
||||
# Set initial status
|
||||
update_status("Not running")
|
||||
add_log_message("Godot MCP Plugin initialized")
|
||||
|
||||
func update_status(status_text: String, is_error: bool = false):
|
||||
status_label.text = "Status: " + status_text
|
||||
if is_error:
|
||||
status_label.add_theme_color_override("font_color", Color(1, 0.3, 0.3))
|
||||
else:
|
||||
status_label.remove_theme_color_override("font_color")
|
||||
|
||||
func add_log_message(message: String):
|
||||
var timestamp = Time.get_datetime_string_from_system()
|
||||
log_display.text += "[" + timestamp + "] " + message + "\n"
|
||||
log_display.scroll_vertical = log_display.get_line_count()
|
||||
|
||||
func _on_start_button_pressed():
|
||||
# This function will be called from the plugin.gd script
|
||||
# when the server is actually started
|
||||
update_status("Running on port " + str(port_field.value))
|
||||
start_button.disabled = true
|
||||
stop_button.disabled = false
|
||||
add_log_message("MCP Server started on port " + str(port_field.value))
|
||||
|
||||
func _on_stop_button_pressed():
|
||||
# This function will be called from the plugin.gd script
|
||||
# when the server is actually stopped
|
||||
update_status("Stopped")
|
||||
start_button.disabled = false
|
||||
stop_button.disabled = true
|
||||
add_log_message("MCP Server stopped")
|
||||
|
||||
# Function to be called from plugin.gd when a client connects
|
||||
func on_client_connected():
|
||||
add_log_message("Client connected")
|
||||
update_status("Client connected")
|
||||
|
||||
# Function to be called from plugin.gd when a client disconnects
|
||||
func on_client_disconnected():
|
||||
add_log_message("Client disconnected")
|
||||
update_status("Running (no clients)")
|
||||
|
||||
# Function to be called from plugin.gd when a command is received
|
||||
func on_command_received(command_type, params):
|
||||
add_log_message("Command received: " + command_type)
|
||||
|
||||
# Function to be called from plugin.gd when a response is sent
|
||||
func on_response_sent(command_type, success):
|
||||
var status = "Success" if success else "Failed"
|
||||
add_log_message("Response sent for " + command_type + ": " + status)
|
||||
@@ -0,0 +1 @@
|
||||
uid://bqabyd7ce60u0
|
||||
@@ -0,0 +1,69 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dxvt86ck6b2a4"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/godot_mcp/ui/mcp_panel.gd" id="1_4g23r"]
|
||||
|
||||
[node name="MCPPanel" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_4g23r")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="StatusPanel" type="PanelContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="StatusLabel" type="Label" parent="VBoxContainer/StatusPanel"]
|
||||
layout_mode = 2
|
||||
text = "Status: Not running"
|
||||
|
||||
[node name="ConfigPanel" type="PanelContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/ConfigPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="PortLabel" type="Label" parent="VBoxContainer/ConfigPanel/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Port:"
|
||||
|
||||
[node name="PortField" type="SpinBox" parent="VBoxContainer/ConfigPanel"]
|
||||
layout_mode = 2
|
||||
min_value = 1024.0
|
||||
max_value = 65535.0
|
||||
value = 6400.0
|
||||
alignment = 1
|
||||
|
||||
[node name="ButtonPanel" type="PanelContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/ButtonPanel"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="StartButton" type="Button" parent="VBoxContainer/ButtonPanel"]
|
||||
layout_mode = 2
|
||||
text = "Start Server"
|
||||
|
||||
[node name="StopButton" type="Button" parent="VBoxContainer/ButtonPanel"]
|
||||
layout_mode = 2
|
||||
disabled = true
|
||||
text = "Stop Server"
|
||||
|
||||
[node name="LogPanel" type="PanelContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="LogDisplay" type="TextEdit" parent="VBoxContainer/LogPanel"]
|
||||
layout_mode = 2
|
||||
editable = false
|
||||
wrap_mode = 1
|
||||
@@ -12,4 +12,4 @@ _surfaces = [{
|
||||
"vertex_count": 8,
|
||||
"vertex_data": PackedByteArray("AAAAvwAAgD8AAAAAAAAAPwAAAAAAAAAAAAAAvwAAAAAAAAAAAAAAPwAAgD8AAAAAAAAAAAAAgD8AAAC/AAAAAAAAAAAAAAA/AAAAAAAAAAAAAAC/AAAAAAAAgD8AAAA//3//f////7//f/9/////v/9//3////+//3//f////78AAP9//3//vwAA/3//f/+/AAD/f/9//78AAP9//3//vw==")
|
||||
}]
|
||||
metadata/GodotVersion = "4.5-stable (official)"
|
||||
metadata/GodotVersion = "4.6.2-stable (official)"
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://deh0tfs84csxo
|
||||
uid://deh0tfs84csxo
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://2juaclm8gc1n
|
||||
uid://2juaclm8gc1n
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://cu72rjuvdnnx
|
||||
uid://cu72rjuvdnnx
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://wckg68rm05vd
|
||||
uid://wckg68rm05vd
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://dmpm4vrmag0ru
|
||||
uid://dmpm4vrmag0ru
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://b1ddeyowx86m3
|
||||
uid://b1ddeyowx86m3
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://usxgr64t746m
|
||||
uid://usxgr64t746m
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://bk4wcnwns36qk
|
||||
uid://bk4wcnwns36qk
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://cdfq5jjtnlcwg
|
||||
uid://cdfq5jjtnlcwg
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://60a3gi7u2kf
|
||||
uid://60a3gi7u2kf
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://cp54123dwlv7j
|
||||
uid://cp54123dwlv7j
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://dii7jpdyaypc6
|
||||
uid://dii7jpdyaypc6
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://ct0c3akkhiaf
|
||||
uid://ct0c3akkhiaf
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://h3cmhcmf6wwy
|
||||
uid://h3cmhcmf6wwy
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://bi3o8elbtqoni
|
||||
uid://bi3o8elbtqoni
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://cvdyxro7g1dic
|
||||
uid://cvdyxro7g1dic
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://bdx4su8bw3dmw
|
||||
uid://bdx4su8bw3dmw
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://ch7elftpoqayg
|
||||
uid://ch7elftpoqayg
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://c56hanl0enhx2
|
||||
uid://c56hanl0enhx2
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://bdgbdmw2hh77q
|
||||
uid://bdgbdmw2hh77q
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://c4damqkvtgm4i
|
||||
uid://c4damqkvtgm4i
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://cdooqj4aiumdm
|
||||
uid://cdooqj4aiumdm
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://cuplxuwag3dnn
|
||||
uid://cuplxuwag3dnn
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://bpnki8vkbrrer
|
||||
uid://bpnki8vkbrrer
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://brbm3okyt3jwq
|
||||
uid://brbm3okyt3jwq
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://c4hxrek5kx6bn
|
||||
uid://c4hxrek5kx6bn
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://brellka4w2k2s
|
||||
uid://brellka4w2k2s
|
||||
|
||||
@@ -1 +1 @@
|
||||
uid://bcnq5eix75v5b
|
||||
uid://bcnq5eix75v5b
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="oggvorbisstr"
|
||||
type="AudioStreamOggVorbis"
|
||||
uid="uid://dgt3nox7yak72"
|
||||
path="res://.godot/imported/pop.ogg-e15d202808be009bef5e04746dba8616.oggvorbisstr"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/pop.ogg"
|
||||
dest_files=["res://.godot/imported/pop.ogg-e15d202808be009bef5e04746dba8616.oggvorbisstr"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=false
|
||||
loop_offset=0
|
||||
bpm=0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
@@ -0,0 +1,24 @@
|
||||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://b2e0ls6ymw45i"
|
||||
path="res://.godot/imported/car_brake.wav-359538a9b1ba4240ae07e54477629dbb.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/vehicles/car/car_brake.wav"
|
||||
dest_files=["res://.godot/imported/car_brake.wav-359538a9b1ba4240ae07e54477629dbb.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
@@ -0,0 +1,24 @@
|
||||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://dlg100ft5f2jy"
|
||||
path="res://.godot/imported/car_engine_accel_loop.wav-25b55bfc6e1d41b17513ac3dd914f463.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/vehicles/car/car_engine_accel_loop.wav"
|
||||
dest_files=["res://.godot/imported/car_engine_accel_loop.wav-25b55bfc6e1d41b17513ac3dd914f463.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=1
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
@@ -0,0 +1,24 @@
|
||||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://cljhbkwcswalc"
|
||||
path="res://.godot/imported/car_engine_drive_loop.wav-be0d54cca48b174deaff89a90d5364c3.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/vehicles/car/car_engine_drive_loop.wav"
|
||||
dest_files=["res://.godot/imported/car_engine_drive_loop.wav-be0d54cca48b174deaff89a90d5364c3.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=1
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
@@ -0,0 +1,24 @@
|
||||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://c28v6t3txgn8w"
|
||||
path="res://.godot/imported/car_engine_idle_loop.wav-56323a2fbc32742f6519b3630f97c275.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/vehicles/car/car_engine_idle_loop.wav"
|
||||
dest_files=["res://.godot/imported/car_engine_idle_loop.wav-56323a2fbc32742f6519b3630f97c275.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=1
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
@@ -0,0 +1,24 @@
|
||||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://bhmyl3ie10u53"
|
||||
path="res://.godot/imported/car_enter.wav-aeff3918a465be3f557bb484cf84ed62.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/vehicles/car/car_enter.wav"
|
||||
dest_files=["res://.godot/imported/car_enter.wav-aeff3918a465be3f557bb484cf84ed62.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
@@ -0,0 +1,24 @@
|
||||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://bngm3s2yq2xwi"
|
||||
path="res://.godot/imported/car_exit.wav-f78ac0b868ae38aeb13d15881f6c3491.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/vehicles/car/car_exit.wav"
|
||||
dest_files=["res://.godot/imported/car_exit.wav-f78ac0b868ae38aeb13d15881f6c3491.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
@@ -0,0 +1,24 @@
|
||||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://bq2d35mekg4il"
|
||||
path="res://.godot/imported/car_hit.wav-5f5ca7b335ab69bea356887a03a1eacc.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/vehicles/car/car_hit.wav"
|
||||
dest_files=["res://.godot/imported/car_hit.wav-5f5ca7b335ab69bea356887a03a1eacc.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
@@ -0,0 +1,24 @@
|
||||
[remap]
|
||||
|
||||
importer="wav"
|
||||
type="AudioStreamWAV"
|
||||
uid="uid://y38ybkt3uxik"
|
||||
path="res://.godot/imported/car_horn.wav-4f978ca1d198f5c6c4a5fcfab9ca1ccc.sample"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/audio/vehicles/car/car_horn.wav"
|
||||
dest_files=["res://.godot/imported/car_horn.wav-4f978ca1d198f5c6c4a5fcfab9ca1ccc.sample"]
|
||||
|
||||
[params]
|
||||
|
||||
force/8_bit=false
|
||||
force/mono=false
|
||||
force/max_rate=false
|
||||
force/max_rate_hz=44100
|
||||
edit/trim=false
|
||||
edit/normalize=false
|
||||
edit/loop_mode=0
|
||||
edit/loop_begin=0
|
||||
edit/loop_end=-1
|
||||
compress/mode=2
|
||||
@@ -1,30 +1,30 @@
|
||||
# weapon.gd
|
||||
extends Resource
|
||||
class_name iWeapon
|
||||
# This acts as an interface base class.
|
||||
|
||||
# --- Common Stats ---
|
||||
@export var weapon_name: String = "Unnamed Weapon"
|
||||
@export var damage: float = 10.0
|
||||
@export var attack_speed: float = 1.0 # attacks per second
|
||||
@export var range: float = 1.5 # meters; melee = short, ranged = long
|
||||
@export var knockback: float = 0.0
|
||||
@export var stamina_cost: float = 5.0
|
||||
|
||||
# --- Ranged‑specific Stats ---
|
||||
@export var projectile_scene: PackedScene # null for melee
|
||||
@export var projectile_speed: float = 20.0
|
||||
@export var ammo_type: String = "" # e.g. "arrows", "bullets"
|
||||
@export var ammo_per_shot: int = 1
|
||||
|
||||
# --- Melee‑specific Stats ---
|
||||
@export var swing_arc: float = 90.0 # degrees
|
||||
@export var hitbox_size: float = 1.0
|
||||
|
||||
# --- Interface Methods ---
|
||||
func attack(user):
|
||||
push_error("Weapon.attack() not implemented in subclass")
|
||||
return null
|
||||
|
||||
func can_attack(user) -> bool:
|
||||
return true
|
||||
# weapon.gd
|
||||
extends Resource
|
||||
class_name iWeapon
|
||||
# This acts as an interface base class.
|
||||
|
||||
# --- Common Stats ---
|
||||
@export var weapon_name: String = "Unnamed Weapon"
|
||||
@export var damage: float = 10.0
|
||||
@export var attack_speed: float = 1.0 # attacks per second
|
||||
@export var range: float = 1.5 # meters; melee = short, ranged = long
|
||||
@export var knockback: float = 0.0
|
||||
@export var stamina_cost: float = 5.0
|
||||
|
||||
# --- Ranged‑specific Stats ---
|
||||
@export var projectile_scene: PackedScene # null for melee
|
||||
@export var projectile_speed: float = 20.0
|
||||
@export var ammo_type: String = "" # e.g. "arrows", "bullets"
|
||||
@export var ammo_per_shot: int = 1
|
||||
|
||||
# --- Melee‑specific Stats ---
|
||||
@export var swing_arc: float = 90.0 # degrees
|
||||
@export var hitbox_size: float = 1.0
|
||||
|
||||
# --- Interface Methods ---
|
||||
func attack(user):
|
||||
push_error("Weapon.attack() not implemented in subclass")
|
||||
return null
|
||||
|
||||
func can_attack(user) -> bool:
|
||||
return true
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bi13nqi11oqhx"
|
||||
path="res://.godot/imported/AshlingSwarmer.glb-69896cc28ddf5352ad63aa98f43893d5.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/AshlingSwarmer.glb"
|
||||
dest_files=["res://.godot/imported/AshlingSwarmer.glb-69896cc28ddf5352ad63aa98f43893d5.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_name_suffixes=true
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=2
|
||||
gltf/embedded_image_handling=1
|
||||
@@ -48,6 +48,7 @@ blender/meshes/colors=false
|
||||
blender/meshes/uvs=true
|
||||
blender/meshes/normals=true
|
||||
blender/meshes/export_geometry_nodes_instances=false
|
||||
blender/meshes/gpu_instances=false
|
||||
blender/meshes/tangents=true
|
||||
blender/meshes/skins=2
|
||||
blender/meshes/export_bones_deforming_mesh_only=false
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
Copyright (c) 2023 Manik Sharma.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
Car Demo by Manik Sharma
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -3,13 +3,13 @@
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://cpuebxqhtv72i"
|
||||
path="res://.godot/imported/humanFemale.glb-45dfb97e0f5fa98244d8cb6255565c65.scn"
|
||||
uid="uid://civr7hlbf2kqb"
|
||||
path="res://.godot/imported/Wheel.glb-dddddd96691989c3e912750c9a47a858.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/humanFemale.glb"
|
||||
dest_files=["res://.godot/imported/humanFemale.glb-45dfb97e0f5fa98244d8cb6255565c65.scn"]
|
||||
source_file="res://assets/models/vehicles/doge/Wheel.glb"
|
||||
dest_files=["res://.godot/imported/Wheel.glb-dddddd96691989c3e912750c9a47a858.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 MiB |
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bpklxkc61avg6"
|
||||
path.s3tc="res://.godot/imported/Wheel_RIMMUSCLE_01_DIF.png-5bb5174c5332f74f16abee062d1ed24a.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "cd5730d572d3e9053a526f83b6971226"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/vehicles/doge/Wheel_RIMMUSCLE_01_DIF.png"
|
||||
dest_files=["res://.godot/imported/Wheel_RIMMUSCLE_01_DIF.png-5bb5174c5332f74f16abee062d1ed24a.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
|
After Width: | Height: | Size: 1.0 MiB |
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://djs3o5hanxb70"
|
||||
path.s3tc="res://.godot/imported/Wheel_RIMMUSCLE_01_MET-RIMMUSCLE_01_ROUGH.png-bf036ae2ba8ef4208853e0caa49ac9e7.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "ee91568e12f40d7fce962016fe4791c0"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/vehicles/doge/Wheel_RIMMUSCLE_01_MET-RIMMUSCLE_01_ROUGH.png"
|
||||
dest_files=["res://.godot/imported/Wheel_RIMMUSCLE_01_MET-RIMMUSCLE_01_ROUGH.png-bf036ae2ba8ef4208853e0caa49ac9e7.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
|
After Width: | Height: | Size: 1.6 MiB |
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cxufd33f0bqsx"
|
||||
path.s3tc="res://.godot/imported/Wheel_RIMMUSCLE_01_NRM.png-3149169313dea5a53591f1b5ae2411f6.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "7d86721466688c1cd90634fe6d2f953a"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/vehicles/doge/Wheel_RIMMUSCLE_01_NRM.png"
|
||||
dest_files=["res://.godot/imported/Wheel_RIMMUSCLE_01_NRM.png-3149169313dea5a53591f1b5ae2411f6.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=1
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=1
|
||||
roughness/src_normal="res://assets/models/vehicles/doge/Wheel_RIMMUSCLE_01_NRM.png"
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
@@ -0,0 +1,42 @@
|
||||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dvgiooankbnw3"
|
||||
path="res://.godot/imported/doge-body.glb-d066dc7fd60eda6d05736bc65e3c5ffe.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/models/vehicles/doge/doge-body.glb"
|
||||
dest_files=["res://.godot/imported/doge-body.glb-d066dc7fd60eda6d05736bc65e3c5ffe.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
nodes/apply_root_scale=true
|
||||
nodes/root_scale=1.0
|
||||
nodes/import_as_skeleton_bones=false
|
||||
nodes/use_name_suffixes=true
|
||||
nodes/use_node_type_suffixes=true
|
||||
meshes/ensure_tangents=true
|
||||
meshes/generate_lods=true
|
||||
meshes/create_shadow_meshes=true
|
||||
meshes/light_baking=1
|
||||
meshes/lightmap_texel_size=0.2
|
||||
meshes/force_disable_compression=false
|
||||
skins/use_named_skins=true
|
||||
animation/import=true
|
||||
animation/fps=30
|
||||
animation/trimming=false
|
||||
animation/remove_immutable_tracks=true
|
||||
animation/import_rest_as_RESET=false
|
||||
import_script/path=""
|
||||
materials/extract=0
|
||||
materials/extract_format=0
|
||||
materials/extract_path=""
|
||||
_subresources={}
|
||||
gltf/naming_version=2
|
||||
gltf/embedded_image_handling=1
|
||||
|
After Width: | Height: | Size: 2.1 MiB |