Final delivery by Enderdogs

Problem and Solution Overview

Managing land usage in a Minecraft multiplayer environment requires structure, fairness, and clear governance to avoid conflicts between players building in shared worlds. To address this, we have implemented a digital building permit solution using the Microsoft Power Platform. Dataverse serves as the core data foundation, Power Pages provides a user-friendly portal where players apply for building permits, and Dynamics 365 Copilot Service Workspace supports case management and escalation when human review is required.


When submitting an application, players define the full build area using start and end (x, y, z) coordinates and describe in detail what they plan to build. This information is stored in Dataverse and made available through Microsoft Fabric to a set of agents built in Microsoft Foundry. Multiple agents analyze each application in parallel, evaluating coordinates and descriptions to detect overlaps with existing builds, restricted zones, excessive depth or height, and other potential rule breaches. The agents operate with access to the critical tables and fields in the case management process, ensuring decisions are based on authoritative and up-to-date data.


If all automated checks pass, the application is deemed ready for approval and a building permit is granted. If clear violations are identified, the application can be rejected or escalated for manual review. Power Automate orchestrates the overall process, handling status changes and approvals, while Customer Insights Journeys is used to notify applicants via SMS and email. Applicants are informed when their permit has been approved, rejected, or requires further review, and chat agents provide real-time interaction and support throughout the application lifecycle. The result is a scalable, automated, and transparent system that protects player creations, minimizes conflicts, and maintains order across the multiplayer server.

Redstone realm

As a Minecraft server admin it is difficult to resolve neighbor problems, and who was where first, and so on.  Without organizing who owns what, and what rules apply where mayhem is inevitable.

Additionally approving applications based on zoning and researching what rules apply where, and what permits apply for what zoning, and overlapping zones is time consuming, and might require a team that knows the server well if scaled up.

This is why we have made the block permit solution. It leverages AI to do research, validate the risk, and comment on permit applications. It makes the process take minutes, not months/weeks.

We leverage agent pods (Microsoft Foundry Workflows) that are dedicated AI teams for a specific purpose. For example checking the permit applications compliance with zoning rules for where the application is for.

With these agent teams the research proses is easy, and compliance suggestions, risk analysis, and negotiations are just minutes away.

User interface – How to get a building permit on the Minecraft Server

We are leveraging Power pages for players to apply for a building permit in the portal.
Currently, we are only accepting applications from players with Entra ID.

However, there are plans to evolve the registration process setting up username and password based on email and password with double opt-in authentication.

Home page

The main navigation has five pages, where players can apply for a building permit, as well viewing my applications and building permits.

Application form

Once building permit applications are successfully submitted, they are managed through the case management functionality within Dynamics 365 Copilot Service Workspace. All communications related to the building application process, culminating in the issuance of a permit upon approval, are coordinated via Dynamics 365 Customer Insights.

View my Building applications and Building Permits

Players can also see their building applications and their status (pending, approved or rejectedI) as well as viewing their building permits once approved.

Customer Service representatives can be reached in several ways if players have any questions regarding their permits or applications. Click on the “Send an Email” and your email client will open, then submit; a logic will then create a case in Customer Service.

Governance & Best Practices


The ability to observe everything that happens is important. And we use the Microsoft foundry to observe our agents.

These dashboards provide transparency to the usage of our agents.

But how do we prevent our agents from just “halusinating” the rules and decisions. And how do we prevent the fact that sometimes it just does not find all the data we want.

The solution is an agent that is specifically designed to be critical and give feedback to the researcher agents. Essentially giving the work of saying “try harder” to an agent. Each instance of the combination: Fabric data agent, Microsoft foundry agent, and read team agent is placed in a foundry workflow that works as a agent pod that makes shure that it figures out the correct answer.

Identities are important throughout the usage of agents. To be able to use the Fabric data agents you have to have access in fabric, even when you use the workflows. This means that the container apps that hosts the Foundry workflows as a API has to have a managed identity that has access in fabric.

The illustration below shows the apps in use to manage the approval process.

Data & AI

If you don’t have good data, you cant have good AI.

We might only have a single data scientist in our team that has 3 months experience with the role. But that does not mean that we don’t have data traveling from Dataverse to fabric and a medallion structure.

We have a dataflow. This is not optimal, but in our tenant the linking directly to fabric through shortcuts was broken.  Shortcuts was the option A, but we had to adapt to use plan B.

We have a medallion structure that is made in the spirit of a data scientist.

In our bronze layer we just get the data to where it should be.
In our silver layer we filter out the data we do not want to use.
And in our gold layer we make the data useful with nice merges and useful tables.
There are many ways to do a medallion structure, and this does the job I want it to do, but there is room for improvement in the silver layer.

This is the part where I rip the band aid off and say we have not had time to do power BI but we have visualization of our data at least.

Data is at the core of our solution. And as a verry new scientist that is way better at AI than data I know ai will out preform me by far. That’s why mining in our data is done with Fabric data agent.

The example above is a query created by Fabric data agent to figure out the contents of permit with the ID A100C206-FEF8-F011-92B9-00224806C768. In this case it searches in bronze for demo purposes.

These fabric data agents are further used by implementing in to other agents like Copilot, and Microsoft Foundry agents. These implementations help drive data driven decisions, and empowers humans to make data driven decisions quicker, and more accurately.

Low-Code

Low Code is NOT Dead… Not for me, not for us, not for the Enderdogs.

That Low Code is dead is an expression that we have heard for a while.. and yes we do see that Agents will do more of the Low Code than we do today. But Still, there is so much we CAN do with so little.

Our main purpose here was to create a solution within Minecraft. Our Business Case is that you need to have a permit before you can start to build your building in Minecraft, and for that we use;

  • Power Pages
  • Dynamics Customer Service
  • Power Platform
  • Contact Center

We also use Microsoft Fabric and Microsoft Foundr.

We start in Power Pages, where the Applicant can start to create an application. The Application is built with standard schema in Power Pages. When the application is created, we send it into Dynamics CE, to send we use an power automate.

In Dynamics CE, customer service and Dataverse we get the application as a case.
And within the case we have the application. N:1
Now we can start the process that handles the case.

The Approval Process

First screening is done with the use of AI. The ai can comment the case, give suggestions, negotiate, and do risk analysis for the application. When the Agent is ready it sends back to Dataverse an updated status for Approved or Rejetcted. We are also able to Approve or Reject manually if the agents decides that it is required.

Connected To Dynamics Marketing (Customer Insight Journey).
In Customer Insight Journey we have created a trigger that gets the data from the Case in Dynamics Customer Service.
We are creating a journey that sends out emails to those who has been Approved or rejected.

Contact Center

We have set up a chat channel from the contact center, that is integrated in the portal
The setup for channels is configured in the Customer Workspace Admincenter.
After the setup we copy the code and add it into the portal. And Whola you have installed a chat so that the user easily can chat directly to you.
An Agent starts the conversation, but it can easily connect you to an human resource.
This Agent is configured in Copilot Studio.

Now the Human Agent can start the conversation with the person that is on the other side.

Copilot helps store the conversation on your case

Record Creation and update Rule.

We have also configured the Record Creation and Update Rule to manage emails from the web.

The best part of this is that you do not have to do so much because it is already configured for you. You just have to add your requirement for the case.

And activate it and you are good to go.

Connected to Teams and Outlook

The Bible

Thank you for the tip

We use planner to create task in M365

Booking

We can store all our documents in SharePoint and connect it to Dynamics 365

And pf course collaborate with Microsoft Copilot.

Code connessieur

We love code so much that we code inn to solutions that is not meant to be coded in yet.  

We use a total of 5 coding languages in our solution, Powershell, Python, Terraform, C#, Bash.

We have IaC on all the infrastructure in Azure by using Terraform.

This includes the Foundry Workflows

Container apps:

And AI agents:


Our entire terraform infrastructure is built on ease of config, and vibe code friendliness (because that is a thing we need to think about now).
all foundry configs are folder and JSON based

This config will create 10 agents, 4 flows, and one model.

The same mindset works for the services deployments in container applications. Just add your script, and config in a folder, and it wil just deploy the service infra.

But Iac is far from the only place we have code.

We have notebooks in fabric that create valuable data and really mines for pure diamonds in our data.

And yes it is vibe coded, but it works flawlessly.

Digital Transformation

As a player at a multiplayer server it feels good to have a space you can call your own regardless of what the other players think. Permits are a nice way to claim a area as your own, and proving that you are the rightful owner of the land.

Going beyond that it can be a good tool to make shure players are aligned on common areas by adding zoning rules. The combination makes it really easy to manage what gets built where.
A good example can be a cabin area with thick trees. The zonining rule can dictate that “No open fires are allowed unless inspected and approved. Height limit 25 blocks. Size limit 40×40. Minnimum distance to approved permits 50 blocks. Styling must be mainly stone and wood.”

The zoning description would make the zone only approve “cabin like” permits.

But Permits are not cool if you use hours to apply, and months before you get the permits approved(like in the real world).

The application process is super simple, and have good user instructions for the end users to understand the process.

But what happens when you have sent the application. How does it approve the application, and help humans approve/make decisions.

This is where AI comes inn to the picture. The firs screening of all permit applications are done with AI. We have a team of 14 AI agents. We have dedicated agents for validating the coning compliance, assessing risk of the application, finding out if neighbors should be warned, and negotiating the permit terms if its close to valid.

These agents have origin in Microsoft foundry, but they are each connected to their own Fabric data agent that they can communicate their data investigation needs to, and it will figure out the data.

The docker container that contains unmined and also run.sh, a bash script to run unmined. Chose this instead of building a console app because it’s already running linux. This is the code to run the unmined console, the environment variable area is to limit the size of the map so it doesn’t turn to big and takes to long. Uploads the rendered imaged into Azure Blob storage.

All cases that are approved can easily be viewed in Dynamic365.

We can also see the approved applications in a view in Zone Manager portal

The Approval process runs with Customer Insight journey

Custom code and Web API
Fully functional, client-side JavaScript implementation for a Minecraft zone and application management system. The code is intended for integration with Power Pages/Power Platform sites, with extension points for backend connections (Dataverse, Power Automate). The manager supports zone creation, application workflow, and interactive map visualizations.


1. Global State Management

A single source of truth for dynamic, interactive components.

const STATE = {
    zones: [],         // Created zones
    map: [],           // Zones currently shown on the map (deploy queue)
    applications: [],  // Building/mining applications
    zoom: 1,           // Map zoom factor
    activeTab: ‘applications’
};

  • Benefit: Keeps all UI in sync with code-driven updates.


2. Zone and Application Data Models

  • Zones: Each zone has coordinates (startX/Y/Z, endX/Y/Z), biome, category, protection and PvP flags, maxPlayers, and unique id.
  • Applications: Building requests featuring playerName, role, experience, requestedZone, type, dimensions, and status.

3. Application & Zone CRUD Logic

Processing Applications (Approve/Reject/Delete)

function handleApprove(id) {
    const app = STATE.applications.find(a => a.id === id);
    if (app) { app.status = ‘approved’; updateStats(); renderApplications(); }
}

  • Benefit: Simple, direct admin workflow for zone building requests.

4. Map Rendering and Visualization

Dynamic Zone Placement and SVG Drawing

function renderMapCanvas() {
    STATE.map.forEach((zone, index) => {
        const zoneElement = createZoneElement(zone, index);
        canvas.appendChild(zoneElement);
    });
}

function createZoneElement(zone, seed) {
    // Organic SVG shape per zone (see generateZoneSVG)
}

Example SVG Generation for “Organic” Zone Shape:

function generateZoneSVG(zone, width, height, seed) {
    // Color per zone category, organic curved borders using calculated path
}

  • Benefit: Makes map visually attractive and clear to use.

Application Marker Display

Pending applications appear as building icons on the map, using coordinate and type data.

5. Tab Navigation and UI Management

Tab switching logic:

function switchTab(tabName) {
    STATE.activeTab = tabName;
    // Update UI classes, render specific content by tab
}

  • Benefit: Mimics SPA-style navigation; content fetch is scalable (supports async API integration).

6. User Feedback & Validation

  • Error Message Display: When a form is invalid or zones overlap.
  • Success Alerts: E.g., after deployments or successful creation.
  • Confirmation Dialogs: For destructive actions (deletion, deploy).

7. Extensibility & Integration Points

Places in the code marked with // TODO are prepared for linking live flows to Dataverse and Power Automate APIs:

// TODO: Call Power Automate flow to update Dataverse

Usage Instructions

  1. Embed zone-manager.js in a Power Pages site alongside the appropriate HTML structure (element IDs must match).
  2. Edit sample data in loadSampleData() as needed, or replace with calls to backend API/Dataverse for production.
  3. Manage zones/applications through forms, buttons, and interactive map.
  4. Trigger deploy to simulate finalizing zone layouts (extend deployment logic as needed).
  • API Integration: Connect event hooks to Dataverse/Power Automate for real data handling.
  • Security: Implement server-side validation for production.
  • Styling: Enhance CSS for better responsive usability.
  • Performance Tuning: Optimize for large numbers of zones/applications as needed.

3D Zone Overlap Logic

function checkZoneOverlap(zone1, zone2) {
    // …math for checking bounding box overlap in X, Y, Z…
    return overlapX && overlapY && overlapZ;
}

Zone SVG Path Generation (“Organic” Shape)

function generateOrganicPath(width, height, seed) {
    // Generates smooth, wavy polygon for zone display
}

Application Card Render (with actions)

function createApplicationCard(app) {
    // Renders HTML for player requests, with approve/reject buttons
}

Delivery Complete: Ready for Acceptance & Integration

  • Client-side sample and demonstration code is robust.
  • Extendable for backend integration; clearly documented.
  • Clean architecture for zone/app management and map interface.

Azure Functions

The idea was to use Power automate to trigger the Azure functions.

The PostRenderFunction receives a .zip file of the whole minecraft map. Validate the zip file and create a new “Render Job” row in Dataverse and use that GUID to send as naming of the .zip file. After the blob has been saved it will run the Azure Container Instance. And return message of Job ID, status “Queued” since it has been sent to the ACI. And the name of the world Blob Storage.

The GetRendeFunction will receive the JobID and check against “Render Jobs”. And if it has ran it will return the image. If not it will check against Blob storage with the GUID of the file. If it’s in rendered it will return the rendered image and change the status of the job.

OUR TENANT IS F**KED

The count of things we have broken is more things that are working as intended. No offense microsoft but it is mostly to blame on the backed, and totally not on the end user.

1: we have broken the integration to fabric from dataverse so hard the judges could not fix it.

2: We have broken azure so hard that when i own the subscription as owner, GA, and AI owner i still cant create Workflows in Microsoft foundry through the portal, but when i do it through sketchy powershell it works 1 out of 10 times. this also counts for creating agents, and models. something broke during the hackathon. what? why? We dont know.

Plug N’ Play

We have now connect to Microsoft Teams and Outlook,

By connecting Microsoft Teams and Outlook with Dynamics 365, we can now work seamlessly from both platforms. This integration brings communication, tasks, and customer data together in one place, making collaboration faster and more efficient. It reduces context switching, saves time, and improves visibility, all while solving real business needs and supporting smarter, more productive ways of working.

Enderdogs landing zone

Just a showcase of our base. We had some late night gaming with friends.

Netherportal in the Dragons mouth and a hanging end portal

Elevator down to the end cave

Chilling area

Bar

Observatory

The big eye of ender

Vibes

The always observing eye of the cave

Building Contract With One Flow

When a building application is approved:

  • The system triggers a secure API call to Oneflow contract service.
  • A new contract is automatically generated, capturing the agreement and relevant building details.
  • The result is logged and/or linked directly in the admin interface for easy reference and auditing.

This integration ensures:

  • Reduced manual paperwork—everything happens instantly, at the time of approval.
  • Legal or procedural compliance, with each approved build traceably backed by a contract.
  • Seamless user/admin experience: admins don’t need to leave the platform to finalize agreements.

Features Bombing: Admin Zone Manager

Our solution (see screenshot below) showcases all required features and interactions on a single page:

Tab Navigation:
Toggle between Applications, Zone Map, and Create Zone effortlessly, with real-time badge counts.
Live Zone Map Visualization:
Entire map area with visually distinct, SVG-rendered zones (with organic borders), interactive markers, and a deployment cart.
Bulk Deployment Actions:
Deploy multiple selected zones to the server at once.
Zoom & Pan Controls:
Easily adjust the view of the map—smooth, responsive client-side manipulation.
Drop-Down Filters & Categories:
Highlight ‘Building’, ‘Protected’, ‘Not Allowed’, and ‘Trade’ zones with colored legends; display status badges inline.
Zone Properties & Management:
Each zone shows properties (coords, size, players, special flags like “Protected”). Admins can remove zones or trigger further actions directly.
Applications & Requests:
Manage building requests and zone applications within the same interface—switch to applications with a single click.

Sharing is caring

We’re using uNmINd to render a minecraft world into an image to use as a coordinate selector. So we do not have to think about looking and typing the coordinates.

Used this in the Terraform to get the global IP address to whitelisting this network.

/# Used for optional IP-restricted ingress (single IP /32)

data “http” “my_ip” {

  url = “http://ipv4.icanhazip.com”

}

And we’re also connecting to LinkMobility to send SMS to the applicant.

Enhancing Minecraft User Experience with Client-Side Automation


async function getPortalToken() {
if (window.shell?.getTokenDeferred) {
return await shell.getTokenDeferred();
}
const hidden = document.querySelector(“input[name=’__RequestVerificationToken’]”);
if (hidden?.value) return hidden.value;

const res = await fetch(“/_layout/tokenhtml”, { credentials: “same-origin” });
const html = await res.text();
const doc = new DOMParser().parseFromString(html, “text/html”);
return doc.querySelector(“input[name=’__RequestVerificationToken’]”)?.value || “”;
}


async function loadZonesFromWebApi({ putOnMap = false } = {}) {
const select = Object.values(ZONE_FIELDS).join(“,”);
const url = `/_api/${ZONES_ENTITY_SET}?$select=${encodeURIComponent(select)}`;

const token = await getPortalToken();
debugger;
const res = await fetch(url, {
method: “GET”,
headers: {
“Accept”: “application/json”,
“OData-Version”: “4.0”,
“OData-MaxVersion”: “4.0”,

“Prefer”: “odata.include-annotations=\”OData.Community.Display.V1.FormattedValue\””,
“__RequestVerificationToken”: token
},
credentials: “same-origin”
});

if (!res.ok) {
const text = await res.text();
throw new Error(`Web API failed ${res.status}: ${text}`);
}

const data = await res.json();
const rows = data.value || [];

// Map Dataverse row -> your zone object shape
const zones = rows.map(r => ({
id: r[ZONE_FIELDS.id],
name: r[ZONE_FIELDS.name],
// Use formatted values when available, else fallback to numeric value
biome: r[`${ZONE_FIELDS.biome}@OData.Community.Display.V1.FormattedValue`] ?? r[ZONE_FIELDS.biome],
category: r[`${ZONE_FIELDS.category}@OData.Community.Display.V1.FormattedValue`] ?? r[ZONE_FIELDS.category],
startX: String(r[ZONE_FIELDS.startX] ?? “”),

startY: String(r[ZONE_FIELDS.startY] ?? “”),
startZ: String(r[ZONE_FIELDS.startZ] ?? “”),
endX: String(r[ZONE_FIELDS.endX] ?? “”),
endY: String(r[ZONE_FIELDS.endY] ?? “”),
endZ: String(r[ZONE_FIELDS.endZ] ?? “”),
protection: !!r[ZONE_FIELDS.protection],
pvpEnabled: !!r[ZONE_FIELDS.pvpEnabled],
maxPlayers: String(r[ZONE_FIELDS.maxPlayers] ?? “”)
}));

STATE.zones = zones;

if (putOnMap) {
STATE.map = […zones];
updateMapCount();
if (STATE.activeTab === “map”) renderMap();
}

return zones; // if you want to use it elsewhere
}

In our Minecraft solution, we leverage client-side JavaScript to manage the creation and review of user-defined zones and building applications—all with a focus on automation, feedback, and interactive mapping.

Instead of performing repetitive, manual tasks, users interact with a dynamic interface that lets them:

  • Apply for building rights
  • Define protected or Not Allowed zones
  • See approvals, pending, and rejections in real time
  • Visualize all changes on an interactive map

MSCRM-addons Sponsor Badge

I installed Document Core Pack in my solution and started merging fields like a king 👑

Inside the Word template, I easily found my table and fields and merged them into the document. After saving the template, I went back to Dynamics CRM.

Using it was incredibly simple. On the table I worked with in Dynamics, I could just click a button to open the Document Core Pack dialog. From there,

I previewed the document and immediately saw the results.

The next step is even better: now I can create a Power Automate flow that automatically sends the document to the customer who submitted the application.

I also have to say — the support team behind Document Core Pack is absolutely amazing. Thank you for guiding me along the way and making the experience so smooth!